CF878E Numbers on the blackboard

题目链接:CF878E

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

$1\leq n,q\leq 10^5,-10^9\leq a_i\leq10^9$。

Sol

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

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

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

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

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

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

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

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

时间复杂度 $\mathcal O(N\log N)$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#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%10+'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;
}