有一个条件没看到(每次覆盖的数一定是最大的)
我们在这道题中可以只去维护断点(数与数不同的地方)
而由于新的区间覆盖的数字一定是不同于以前的数字,所以这个端点就比较好维护.
对于序列 $p$,覆盖 $[L,R]$ 显然 $1$ ~ $L-2$,$R+1$ ~ $n$ 断点不改变,$L-1$ 与 $R$ 成为新的断点.
那么我们令 $SUM[i]$ 表示前 $1$ ~ $2^i$ 个序列中 $i$ 位置的断点总和.
那么经过依次新的操作,就按照上述方式更新一下 $SUM$ 数组即可.
大概是:
$1$ ~ $L-2$ 与 $R+1$ ~ $n$ 乘以 2 (不变 + 复制)
$L-1$ 与 $R$ 加上 $2^{i-1}$ (对于一半的数组加上新断点)
code:
#include <bits/stdc++.h> #define ll long long #define mod 20050321 #define N 2006 #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; int p[N],SUM[N],tmp[N],n,m; int main() { // setIO("input"); p[0]=1; for(int i=1;i<N;++i) p[i]=(ll)p[i-1]*2%mod; scanf("%d%d",&n,&m); SUM[0]=SUM[n]=1; for(int i=1;i<=m;++i) { int L,R; scanf("%d%d",&L,&R); for(int j=0;j<L-1;++j) (SUM[j]*=2)%=mod; for(int j=R+1;j<=n;++j) (SUM[j]*=2)%=mod; (SUM[L-1]+=p[i-1])%=mod; (SUM[R]+=p[i-1])%=mod; int ans=0; for(int j=0;j<=n;++j) (ans+=SUM[j])%=mod; printf("%d ",(ans-p[i]+mod)%mod); } return 0; }