HDU4578 Transformation (多操作线段树)

传送门

 

终于过了这道题。。

要注意标记之间的影响,和add操作时更新求和的顺序。

 

same 区间每个数设置为x标记   

mult  区间每个数乘x标记

add  区间每个数加x标记

 

①:当打same标记时,mult标记和add标记就没用了,要初始化。

②:当打mult标记时,add标记也要乘相应的值。

 

---------------求和可以递推过来---------------

1次方求和就正常求和

即:sum1[rt]=sum1[rt]+(r-l+1)*val;

2次方 可以由 (x+val)= x2+val2+2*x*val

即:sum2[rt]=sum2[rt]+2*sum1[rt]*val+(r-l+1)*val*val;

3次方 可以由 (x+val)= x3+val3+3*x2*val+3*x*val2

即:sum3[rt]=sum3[rt]+(r-l+1)*val*val*val+3*sum2[rt]*val+3*sum1[rt]*val*val;

 

再次注意  add求和要按照sum3,sum2, sum1的顺序!

 

算是又对取模有了一点了解。。

a*b*c*d  取模为  (a*b%mod) * (c*d%mod) %mod

a+b*c*d+3*a*b*c*d  取模为 (a + (b*c)%mod*d + 3*((a*b)%mod)*((c*d)%mod)%mod)%mod

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int mod=10007;
  5 const int maxx=100010;
  6 
  7 ll add[maxx<<2],mult[maxx<<2],same[maxx<<2];
  8 ll sum1[maxx<<2],sum2[maxx<<2],sum3[maxx<<2];
  9 
 10 int n,m,sum;
 11 
 12 void pushup(int rt) {
 13     sum1[rt]=(sum1[rt<<1]+sum1[rt<<1|1])%mod;
 14     sum2[rt]=(sum2[rt<<1]+sum2[rt<<1|1])%mod;
 15     sum3[rt]=(sum3[rt<<1]+sum3[rt<<1|1])%mod;
 16 }
 17 
 18 void build(int l,int r,int rt) {
 19     add[rt]=same[rt]=0;
 20     mult[rt]=1;
 21     if(l==r) {
 22         sum1[rt]=sum2[rt]=sum3[rt]=0;
 23         return;
 24     }
 25     int mid=(l+r)>>1;
 26     build(l,mid,rt<<1);
 27     build(mid+1,r,rt<<1|1);
 28     pushup(rt);
 29 }
 30 
 31 void pushdown(int rt,int len) {  //下传标记
 32     if(same[rt]) {
 33         sum1[rt<<1]=(len-(len>>1))*same[rt]%mod;
 34         sum1[rt<<1|1]=(len>>1)*same[rt]%mod;
 35         sum2[rt<<1]=((len-(len>>1))*same[rt]%mod)*same[rt]%mod;
 36         sum2[rt<<1|1]=((len>>1)*same[rt]%mod)*same[rt]%mod;
 37         sum3[rt<<1]=((len-(len>>1))*same[rt]%mod)*(same[rt]*same[rt]%mod)%mod;
 38         sum3[rt<<1|1]=((len>>1)*same[rt]%mod)*(same[rt]*same[rt]%mod)%mod;
 39         same[rt<<1]=same[rt<<1|1]=same[rt];
 40         add[rt<<1]=add[rt<<1|1]=0;  //也需要改变
 41         mult[rt<<1]=mult[rt<<1|1]=1; //也需要改变
 42         same[rt]=0;
 43     }
 44     if(mult[rt]!=1) {
 45         mult[rt<<1]=mult[rt<<1]*mult[rt]%mod;
 46         mult[rt<<1|1]=mult[rt<<1|1]*mult[rt]%mod;
 47         add[rt<<1]=add[rt<<1]*mult[rt]%mod; //改变
 48         add[rt<<1|1]=add[rt<<1|1]*mult[rt]%mod;  //改变
 49         sum1[rt<<1]=sum1[rt<<1]*mult[rt]%mod;
 50         sum1[rt<<1|1]=sum1[rt<<1|1]*mult[rt]%mod;
 51         sum2[rt<<1]=(sum2[rt<<1]*mult[rt]%mod)*mult[rt]%mod;
 52         sum2[rt<<1|1]=(sum2[rt<<1|1]*mult[rt]%mod)*mult[rt]%mod;
 53         sum3[rt<<1]=(sum3[rt<<1]*mult[rt]%mod)*(mult[rt]*mult[rt]%mod)%mod;
 54         sum3[rt<<1|1]=(sum3[rt<<1|1]*mult[rt]%mod)*(mult[rt]*mult[rt]%mod)%mod;
 55         mult[rt]=1;
 56     }
 57     if(add[rt]) {
 58         add[rt<<1]=(add[rt<<1]+add[rt])%mod;
 59         add[rt<<1|1]=(add[rt<<1|1]+add[rt])%mod;
 60         sum3[rt<<1]=(sum3[rt<<1]+3*sum2[rt<<1]*add[rt]%mod+3*(sum1[rt<<1]*add[rt]%mod)*add[rt]%mod+(add[rt]*add[rt]%mod)*(add[rt]*(len-(len>>1))%mod))%mod;
 61         sum3[rt<<1|1]=(sum3[rt<<1|1]+3*sum2[rt<<1|1]*add[rt]%mod+3*(sum1[rt<<1|1]*add[rt]%mod)*add[rt]%mod+(add[rt]*add[rt]%mod)*(add[rt]*(len>>1)%mod))%mod;
 62         sum2[rt<<1]=(sum2[rt<<1]+2*sum1[rt<<1]*add[rt]%mod+(add[rt]*add[rt]%mod)*(len-(len>>1))%mod)%mod;
 63         sum2[rt<<1|1]=(sum2[rt<<1|1]+2*sum1[rt<<1|1]*add[rt]%mod+(add[rt]*add[rt]%mod)*(len>>1)%mod)%mod;
 64         sum1[rt<<1]=(sum1[rt<<1]+(len-(len>>1))*add[rt]%mod)%mod;
 65         sum1[rt<<1|1]=(sum1[rt<<1|1]+(len>>1)*add[rt]%mod)%mod;
 66         add[rt]=0;
 67     }
 68 }
 69 
 70 void updata(int L,int R, int val,int op,int l,int r,int rt) {
 71     if(L<=l&&R>=r) {
 72         if(op==3) {
 73             same[rt]=val;
 74             mult[rt]=1;  //改变
 75             add[rt]=0;   //改变
 76             sum1[rt]=(r-l+1)*val%mod;
 77             sum2[rt]=((r-l+1)*val%mod)*val%mod;
 78             sum3[rt]=((r-l+1)*val%mod)*(val*val%mod)%mod;
 79         } else if(op==2) {
 80             mult[rt]=mult[rt]*val%mod;
 81             add[rt]=add[rt]*val%mod; //改变
 82             sum1[rt]=sum1[rt]*val%mod;
 83             sum2[rt]=(sum2[rt]*val%mod)*val%mod;
 84             sum3[rt]=(sum3[rt]*val%mod)*(val*val%mod)%mod;
 85         } else if(op==1) {
 86             add[rt]=(add[rt]+val)%mod;
 87             sum3[rt]=(sum3[rt]+3*sum2[rt]*val%mod+3*(sum1[rt]*val%mod)*val%mod+(((r-l+1)*val%mod)*(val*val%mod)%mod))%mod;
 88             sum2[rt]=(sum2[rt]+2*sum1[rt]*val%mod+((r-l+1)*val%mod)*val%mod)%mod;
 89             sum1[rt]=(sum1[rt]+(r-l+1)*val%mod)%mod;
 90         }
 91         return;
 92     }
 93     pushdown(rt,r-l+1);
 94     int mid=(l+r)>>1;
 95     if(L<=mid) updata(L,R,val,op,l,mid,rt<<1);
 96     if(R>mid) updata(L,R,val,op,mid+1,r,rt<<1|1);
 97     pushup(rt);
 98 }
 99 
100 ll query(int L,int R,int val,int l,int r,int rt) {
101     if(L<=l&&R>=r) {
102         if(val==1) {
103             return sum1[rt]%mod;
104         } else if(val==2) {
105             return sum2[rt]%mod;
106         } else return sum3[rt]%mod;
107     }
108     ll sum=0;
109     pushdown(rt,r-l+1);
110     int mid=(l+r)>>1;
111     if(L<=mid) sum=(sum+query(L,R,val,l,mid,rt<<1))%mod;
112     if(R>mid) sum=(sum+query(L,R,val,mid+1,r,rt<<1|1))%mod;
113     return sum;
114 }
115 
116 int main() {
117     while(~scanf("%d%d",&n,&m)) {
118         if(n==0&&m==0) break;
119         build(1,n,1);
120         while(m--) {
121             int op,x,y,val;
122             scanf("%d%d%d%d",&op,&x,&y,&val);
123             if(op==4) {
124                 printf("%lld\n",query(x,y,val,1,n,1));
125             }
126             else updata(x,y,val,op,1,n,1);
127         }
128     }
129 }
View Code

 

 

 

 

 

posted @ 2019-07-09 14:12  Frontierone  阅读(154)  评论(0编辑  收藏  举报