• Transformation


    题意:

    给一初始为0的数列,要求进行,区间$set,add,multiply$,维护 $sum{{a_i}^{p}}$ (0<=p<=3)

    解法:

    首先考虑区间加c的影响,记$S(p)$表示当前区间的$sum{{a_i}^p}$

    这样有,$$sum{(a_i + c)^p} = sum_{r=0}^p{C_p^r S(p-r) c^r}$$。

    这样我们只要维护 3 个标记 $set,add,multiply$ 即可,

    考虑标记的合并方式。

    首先只看$add,multiply$,记$qv$为当前操作的数值,

    这样有$sum' = multiply imes sum + add$

    将一个乘以$qv$的标记推下来有:$sum' = (qv cdot multiply) imes sum + (add cdot qv)$

    将一个加上$qv$的标记推下来有:$sum' = multiply imes sum + (add+qv)$

    注意我们每个点可能同时存在 $add, multiply$ ,这样要先下推 $multiply$。

    考虑$set$标记,$set$标记可以覆盖其他的所有标记,而其他的标记和$set$合并后都可以表示为一个$set$标记。

    PS:注意在叶子节点不要push(多组数据的时候会错)

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 #define N 100010
      6 #define l(x) ch[x][0]
      7 #define r(x) ch[x][1] 
      8 #define P 10007
      9 
     10 using namespace std;
     11 
     12 int n,m,totn;
     13 int ch[N<<1][2],sumv[N<<1][4];
     14 int addv[N<<1],mulv[N<<1],setv[N<<1];
     15 int C[5][5];
     16 
     17 void push(int x)
     18 {
     19     if(setv[x]!=-1)
     20     {
     21         setv[l(x)]=setv[x];
     22         addv[l(x)]=0;
     23         mulv[l(x)]=1;
     24         
     25         setv[r(x)]=setv[x];
     26         addv[r(x)]=0;
     27         mulv[r(x)]=1;
     28         
     29         int tmp=setv[x];
     30         for(int i=1;i<=3;i++)
     31         {
     32             sumv[l(x)][i] = sumv[l(x)][0]*tmp%P;
     33             sumv[r(x)][i] = sumv[r(x)][0]*tmp%P;
     34             tmp = tmp*setv[x]%P;
     35         }
     36         setv[x]=-1;
     37     }
     38     if(mulv[x]!=1)
     39     {
     40         if(setv[l(x)]==-1)
     41         {
     42             mulv[l(x)] = mulv[l(x)]*mulv[x]%P;
     43             addv[l(x)] = addv[l(x)]*mulv[x]%P;
     44         }
     45         else setv[l(x)] = setv[l(x)]*mulv[x]%P;
     46         
     47         if(setv[r(x)]==-1)
     48         {
     49             mulv[r(x)] = mulv[r(x)]*mulv[x]%P;
     50             addv[r(x)] = addv[r(x)]*mulv[x]%P;
     51         }
     52         else setv[r(x)] = setv[r(x)]*mulv[x]%P;
     53         int tmp=mulv[x];
     54         
     55         for(int i=1;i<=3;i++)
     56         {
     57             sumv[l(x)][i] = sumv[l(x)][i]*tmp%P;
     58             sumv[r(x)][i] = sumv[r(x)][i]*tmp%P;
     59             tmp = tmp*mulv[x]%P;
     60         }
     61         
     62         mulv[x]=1;
     63     }
     64     if(addv[x])
     65     {
     66         int Sl[4],Sr[4];
     67         memcpy(Sl,sumv[l(x)],sizeof(sumv[l(x)]));
     68         memcpy(Sr,sumv[r(x)],sizeof(sumv[r(x)]));
     69         
     70         for(int i=1;i<=3;i++)
     71         {
     72             int tmp=1;
     73             sumv[l(x)][i]=0;
     74             sumv[r(x)][i]=0;
     75             for(int j=0;j<=i;j++)
     76             {
     77                 sumv[l(x)][i] += C[i][j]*tmp%P*Sl[i-j]%P;
     78                 if(sumv[l(x)][i]>=P) sumv[l(x)][i]-=P;
     79                 sumv[r(x)][i] += C[i][j]*tmp%P*Sr[i-j]%P;
     80                 if(sumv[r(x)][i]>=P) sumv[r(x)][i]-=P;
     81                 tmp = tmp*addv[x]%P;
     82             }
     83         }
     84         
     85         if(setv[l(x)]==-1) addv[l(x)] = (addv[l(x)]+addv[x])%P;
     86         else setv[l(x)] = (setv[l(x)]+addv[x])%P;
     87         if(setv[r(x)]==-1) addv[r(x)] = (addv[r(x)]+addv[x])%P;
     88         else setv[r(x)] = (setv[r(x)]+addv[x])%P;
     89         addv[x]=0;
     90     }
     91 }
     92 
     93 void update(int x)
     94 {
     95     sumv[x][0]=(sumv[l(x)][0]+sumv[r(x)][0])%P;
     96     sumv[x][1]=(sumv[l(x)][1]+sumv[r(x)][1])%P;
     97     sumv[x][2]=(sumv[l(x)][2]+sumv[r(x)][2])%P;
     98     sumv[x][3]=(sumv[l(x)][3]+sumv[r(x)][3])%P;
     99 }
    100 
    101 int build(int l,int r)
    102 {
    103     int x=++totn;
    104     addv[x]=0;
    105     mulv[x]=1;
    106     setv[x]=-1;
    107     memset(sumv[x],0,sizeof(sumv[x]));
    108     if(l==r)
    109     {
    110         sumv[x][0]=1;
    111         l(x)=0;
    112         r(x)=0;
    113         return x;
    114     }
    115     int mid=(l+r)>>1;
    116     l(x)=build(l,mid);
    117     r(x)=build(mid+1,r);
    118     update(x);
    119     return x;
    120 }
    121 
    122 void add(int x,int l,int r,int ql,int qr,int qv)
    123 {
    124     push(x);
    125     if(ql<=l && r<=qr)
    126     {
    127         addv[x] = qv;
    128         int S[4];
    129         memcpy(S,sumv[x],sizeof(sumv[x]));
    130         for(int i=1;i<=3;i++)
    131         {
    132             int tmp=1;
    133             sumv[x][i]=0;
    134             for(int j=0;j<=i;j++)
    135             {
    136                 sumv[x][i] += C[i][j] * tmp %P * S[i-j]%P;
    137                 if(sumv[x][i]>=P) sumv[x][i]-=P;
    138                 tmp = tmp*qv%P;
    139             }
    140         }
    141         return;
    142     }
    143     int mid=(l+r)>>1;
    144     if(ql<=mid) add(l(x),l,mid,ql,qr,qv);
    145     if(mid<qr)  add(r(x),mid+1,r,ql,qr,qv);
    146     update(x);
    147 }
    148 
    149 void mul(int x,int l,int r,int ql,int qr,int qv)
    150 {
    151     push(x);
    152     if(ql<=l && r<=qr)
    153     {
    154         mulv[x] = qv;
    155         int tmp=qv;
    156         for(int i=1;i<=3;i++)
    157         {
    158             sumv[x][i] = sumv[x][i]*tmp%P;
    159             tmp = tmp*qv%P;
    160         }
    161         return;
    162     }
    163     int mid=(l+r)>>1;
    164     if(ql<=mid) mul(l(x),l,mid,ql,qr,qv);
    165     if(mid<qr)  mul(r(x),mid+1,r,ql,qr,qv);
    166     update(x);
    167 }
    168 
    169 void setd(int x,int l,int r,int ql,int qr,int qv)
    170 {
    171     push(x);
    172     if(ql<=l && r<=qr)
    173     {
    174         setv[x] = qv;
    175         int tmp=qv;
    176         for(int i=1;i<=3;i++)
    177         {
    178             sumv[x][i] = sumv[x][0]*tmp%P;
    179             tmp = tmp*qv%P;
    180         }
    181         return;
    182     }
    183     int mid=(l+r)>>1;
    184     if(ql<=mid) setd(l(x),l,mid,ql,qr,qv);
    185     if(mid<qr)  setd(r(x),mid+1,r,ql,qr,qv);
    186     update(x);
    187 }
    188 
    189 int ask(int x,int l,int r,int ql,int qr,int qk)
    190 {
    191     push(x);
    192     if(ql<=l && r<=qr) return sumv[x][qk];
    193     int mid=(l+r)>>1,ans=0;
    194     if(ql<=mid) ans += ask(l(x),l,mid,ql,qr,qk);
    195     if(mid<qr)
    196     {
    197         ans += ask(r(x),mid+1,r,ql,qr,qk);
    198         if(ans>=P) ans-=P;
    199     }
    200     update(x);
    201     return ans;
    202 }
    203 
    204 int main()
    205 {
    206     C[0][0]=1;
    207     for(int i=1;i<=3;i++)
    208     {
    209         C[i][0]=1;
    210         for(int j=1;j<=i;j++)
    211             C[i][j] = (C[i-1][j-1]+C[i-1][j])%P;
    212     }
    213     while(scanf("%d%d",&n,&m), n&&m)
    214     {
    215         totn=0;
    216         build(1,n);
    217         int cmd,l,r,x;
    218         while(m--)
    219         {
    220             scanf("%d%d%d%d",&cmd,&l,&r,&x);
    221             if(cmd==1) add(1,1,n,l,r,x%P);
    222             else if(cmd==2) mul(1,1,n,l,r,x%P);
    223             else if(cmd==3) setd(1,1,n,l,r,x%P);
    224             else printf("%d
    ",ask(1,1,n,l,r,x));
    225         }
    226     }
    227     return 0;
    228 }
    229 /*
    230 5 5
    231 3 3 5 7
    232 1 2 4 4
    233 4 1 5 2
    234 2 2 5 8
    235 4 3 5 3
    236 0 0
    237 */
    View Code
  • 相关阅读:
    让Vim查找字符忽略大小写
    How to Add a User to Sudoers on Ubuntu
    Docker 批量删除images
    解决 Laradock 安装时候出现 Can't open /home/laradock/.nvm/nvm.sh 的问题
    Add User To Docker Group In Ubuntu Linux
    Parted分区和创建逻辑卷LVM
    How To List Users and Groups on Linux
    How to Install Node.js and NPM on Mac OS
    linux中的alias命令详解
    Hadoop数据类型
  • 原文地址:https://www.cnblogs.com/lawyer/p/6636535.html
Copyright © 2020-2023  润新知