Comet OJ - Contest #14 C 序列

有一个条件没看到(每次覆盖的数一定是最大的)
我们在这道题中可以只去维护断点(数与数不同的地方)

而由于新的区间覆盖的数字一定是不同于以前的数字,所以这个端点就比较好维护.   

对于序列 $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\n",(ans-p[i]+mod)%mod);  
    }
    return 0; 
}

  

 

posted @ 2020-04-21 20:24  EM-LGH  阅读(129)  评论(0编辑  收藏  举报