CF878E Numbers on the blackboard

2022-09-19 13:50:46 浏览数 (2)

CF878E Numbers on the blackboard

题目链接:CF878E

给出 n 个数字,每次询问一个区间 [l,r],对这个区间内部的点进行操作。 每次操作可以合并相邻两个数 x,y 其中 x before y,将它们变成 x 2y 对于每次询问输出当最后只剩下一个数字时,这个数字的最大值。 询问互相独立,答案对 10^9 7 取模。

1leq n,qleq 10^5,-10^9leq a_ileq10^9

Sol

一开始没看到 x before y 和指导胡扯了好久

显然一定是从左到右,如果当前数为非负数,一定将该数与上一块进行合并;如果当前数为非负数,一定是给它单独新开一个块。

如果合并后导致原来一个贡献为负的块贡献变为正了,则继续向前合并,显然这样贡献最大。

最后一定是从后往前依次将每个块合并。

显然最后每个数的贡献一定是 2 的幂,可以提前预处理。

然后把询问离线下来,按照 r 端点排个序然后每次考虑插点合并块即可。

然后左端点所在的块会拆开,但是显然这拆开的部分一定不会与后面合并(这样肯定不优)。

最后有个小细节,合并如何判断正负(在取模之后)?显然如果一个块内的权值之和已经超过了 10^{14} 则一定能把之前的所有块都合并了,于是只需要每个块单独的和先用 long long 存即可。

时间复杂度 mathcal O(Nlog N)

代码语言:javascript复制
#include<bits/stdc  .h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define CI Cn int&
#define gc getchar
#define D isdigit(c=gc())
#define pc(c) putchar((c))
using namespace std;
namespace Debug{
    Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
    Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f  ;cerr<<'='<<x<<",";_debug(f 1,y...);}
    Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
    #define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
    Tp I void read(Ty& x){char c;int f=1;x=0;W(!D) f=c^'-'?1:-1;W(x=(x<<3) (x<<1) (c&15),D);x*=f;}
    Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
    Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x '0'),0):(write(x/10),pc(x '0'),0);}
    Tp I void writeln(Cn Ty& x){write(x),pc('n');}
}using namespace FastIO;
Cn int N=1e5 10,p=1e9 7,Inv2=500000004;
Cn LL inf=1e15;
int n,q,a[N],inv[N],pw[N],stk[N],top;
LL s[N],S[N],SS[N],Ans[N];
struct Que{int l,r,id;}Q[N];
vector<int> v[N];
#define pb push_back
int main(){
    RI i,t;for(read(n,q),pw[0]=inv[0]=1,i=1;i<=n;i  ) read(a[i]),s[i]=(s[i-1] 1LL*(pw[i]=2LL*pw[i-1]%p)*a[i]%p)%p,inv[i]=1LL*inv[i-1]*Inv2%p;
    for(i=1;i<=q;i  ) read(Q[i].l,Q[i].r),Q[i].id=i,v[Q[i].r].pb(i);
    for(i=1;i<=n;i  ){
        stk[  top]=i,S[top]=a[i];
        W(top&&S[top]>0) (1LL<<stk[top]-stk[top-1])>(inf-S[top-1])/S[top]?S[top-1]=inf:S[top-1] =(1<<stk[top]-stk[top-1])*S[top],top--;
        SS[top]=S[top]<inf?(SS[top-1] S[top])%p:s[i];for(auto j:v[i]){
            stk[top 1]=Q[j].r 1,t=upper_bound(stk 1,stk top 2,Q[j].l)-stk;
            Ans[Q[j].id]=((2LL*(SS[top]-SS[t-1] p)%p 1LL*(s[stk[t]-1]-s[Q[j].l-1] p)*inv[Q[j].l]%p)%p p)%p;
        }
    }for(i=1;i<=q;i  ) writeln(Ans[i]);
    return 0;
}

0 人点赞