• bzoj 2962: 序列操作


    Time Limit: 50 Sec  Memory Limit: 256 MB
    Submit: 1179  Solved: 392
    [Submit][Status][Discuss]

    Description

      有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这一段区间中选择c个数相乘的所有方案的和mod 19940417的值。

    Input

      第一行两个数n,q表示序列长度和操作个数。
      第二行n个非负整数,表示序列。
      接下来q行每行输入一个操作I a b c或者 R a b或者Q a b c意义如题目描述。

    Output

      对于每个询问,输出选出c个数相乘的所有方案的和mod19940417的值。

    Sample Input

    5 5
    1 2 3 4 5
    I 2 3 1
    Q 2 4 2
    R 1 5
    I 1 3 -1
    Q 1 5 1

    Sample Output

    40
    19940397
    样例说明
      做完第一个操作序列变为1 3 4 4 5。
      第一次询问结果为3*4+3*4+4*4=40。
      做完R操作变成-1 -3 -4 -4 -5。
      做完I操作变为-2 -4 -5 -4 -5。
      第二次询问结果为-2-4-5-4-5=-20。

    HINT

      100%的数据n<=50000,q<=50000,初始序列的元素的绝对值<=109,I a b c中保证[a,b]是一个合法区间,|c|<=109,R a b保证[a,b]是个合法的区间。Q a b c中保证[a,b]是个合法的区间1<=c<=min(b-a+1,20)。

    Source

     
     
    码农级线段树题目,,,
    子树合并很好想,就是一个卷积;
    标记下传也很好想,我的写法的话是先下传正负再下传add。
    正负修改也很好想,把add和tag打一下标记然后把i是奇数的f[]变成它的相反数即可。
    就是区间加之后的维护有点难度,要推一推式子,但是这里我懒得再推一遍了23333。
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 50005
    #define ha 19940417
    using namespace std;
    int C[maxn][25],n,m,tp,num;
    int a[maxn],le,ri,w,ci[25];
    
    inline int add(int x,int y){
        x+=y;
        return x>=ha?x-ha:x;
    }
    
    inline void init(){
        C[0][0]=1;
        for(int i=1;i<=n;i++){
            tp=min(i,20);
            C[i][0]=1;
            for(int j=1;j<=tp;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
        }
    }
    
    struct node{
        int tag,ad;
        int c[25];
            
        inline void clear(){
            memset(c,0,sizeof(c));
            tag=ad=0;
        }
        
        node operator +(const node &U)const{
            node r;
            r.clear();
            for(int i=0;i<=20;i++) if(c[i])
                for(int j=i;j<=20;j++) if(U.c[j-i])
                    r.c[j]=add(r.c[j],c[i]*(ll)U.c[j-i]%ha);
            
            return r;
        }
    }b[maxn<<2|1],AN;
    char ch;
    
    void build(int o,int l,int r){
        if(l==r){
            b[o].c[0]=1;
            b[o].c[1]=a[l];
            return;
        }
        
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        
        b[o]=b[lc]+b[rc];
    }
    
    inline void work(int o,int d,int len){
        tp=min(len,20);
        ci[0]=1;
        for(int i=1;i<=tp;i++) ci[i]=ci[i-1]*(ll)d%ha;
        b[o].ad=add(b[o].ad,d);
        
        for(int i=20;i;i--){
            int S=i,T=len;
            for(int j=0;j<i;j++,S--,T--){
                b[o].c[i]=add(b[o].c[i],b[o].c[j]*(ll)ci[i-j]%ha*(ll)C[T][S]%ha);
            }
        }
    }
    
    inline void rotate(int o,int len){
        b[o].tag^=1,b[o].ad=ha-b[o].ad;
        for(int i=1;i<=20;i+=2) b[o].c[i]=ha-b[o].c[i];
    }
    
    inline void pushdown(int o,int l,int r){
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        if(b[o].tag){
            rotate(lc,mid-l+1);
            rotate(rc,r-mid);
            b[o].tag=0;
        }
        if(b[o].ad){
            work(lc,b[o].ad,mid-l+1);
            work(rc,b[o].ad,r-mid);
            b[o].ad=0;
        }
    }
    
    void updateX(int o,int l,int r){
        if(l>=le&&r<=ri){
            work(o,w,r-l+1);		
            return;
        }
        
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        pushdown(o,l,r);
        if(le<=mid) updateX(lc,l,mid);
        if(ri>mid) updateX(rc,mid+1,r);
            
        b[o]=b[lc]+b[rc];
    }
    
    void updateY(int o,int l,int r){
        if(l>=le&&r<=ri){
            rotate(o,r-l+1);
            return;
        }
        
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        pushdown(o,l,r);
        if(le<=mid) updateY(lc,l,mid);
        if(ri>mid) updateY(rc,mid+1,r);
        
        b[o]=b[lc]+b[rc];
    }
    
    void query(int o,int l,int r){
        if(l>=le&&r<=ri){
            AN=AN+b[o];
            return;
        }
        
        int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
        pushdown(o,l,r);
        if(le<=mid) query(lc,l,mid);
        if(ri>mid) query(rc,mid+1,r);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            a[i]%=ha;
            if(a[i]<0) a[i]+=ha;
        }
        build(1,1,n);
        
        while(m--){
            ch=getchar();
            while(ch!='I'&&ch!='R'&&ch!='Q') ch=getchar();
            scanf("%d%d",&le,&ri);
            if(ch=='R') updateY(1,1,n);
            else{
                scanf("%d",&w);
                if(ch=='Q'){
                    AN.clear();
                    AN.c[0]=1;
                    query(1,1,n);
                    printf("%d
    ",AN.c[w]);
                }
                else{
                    w%=ha;
                    if(w<0) w+=ha;
                    updateX(1,1,n);
                }
            }
        }
        
        return 0;
    }
    

      

  • 相关阅读:
    【原创】颜色替换的递归算法
    【原创】Hacker学习发展流程图 V1.0
    【转载】基数排序
    【翻译】利用加速度求解位置的算法——三轴传感器
    js高级程序设计——笔记
    java中的多线程——进度1
    数据结构和算法——进度1
    java String字符串——进度1
    java中运算符——进度1
    jquery的插件机制
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8496566.html
Copyright © 2020-2023  润新知