[BZOJ1798][AHOI2009]Seq维护序列 线段树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798
一眼看过去线段树,事实上就是线段树。对于乘和加的两个标记,我们可以规定一个顺序,比如先乘后加。每次乘的时候利用乘法分配律就可以分别更新标记,而加就直接加上去就好了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 int inline readint(){ 7 int Num;char ch; 8 while((ch=getchar())<'0'||ch>'9');Num=ch-'0'; 9 while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0'; 10 return Num; 11 } 12 void outint(int x){ 13 if(x>=10) outint(x/10); 14 putchar(x%10+'0'); 15 } 16 int N,M,P; 17 int sum[(100000<<2)+10],col1[(100000<<2)+10],col2[(100000<<2)+10]; 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 void Pushup(int &rt){ 21 sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%P; 22 } 23 void Build(int l,int r,int rt){ 24 col1[rt]=1; 25 if(l==r){ 26 sum[rt]=readint()%P; 27 return; 28 } 29 int mid=l+r>>1; 30 if(l<=mid) Build(lson); 31 if(r>mid) Build(rson); 32 Pushup(rt); 33 } 34 void Pushdown(int &rt,int &l,int &r){ 35 if(col1[rt]!=1){ 36 col1[rt<<1]=(ll)col1[rt<<1]*col1[rt]%P; 37 col2[rt<<1]=(ll)col2[rt<<1]*col1[rt]%P; 38 sum[rt<<1]=(ll)sum[rt<<1]*col1[rt]%P; 39 col1[rt<<1|1]=(ll)col1[rt<<1|1]*col1[rt]%P; 40 col2[rt<<1|1]=(ll)col2[rt<<1|1]*col1[rt]%P; 41 sum[rt<<1|1]=(ll)sum[rt<<1|1]*col1[rt]%P; 42 col1[rt]=1; 43 } 44 if(col2[rt]){ 45 col2[rt<<1]=(col2[rt<<1]+col2[rt])%P; 46 sum[rt<<1]=((ll)col2[rt]*((l+r>>1)-l+1)%P+sum[rt<<1])%P; 47 col2[rt<<1|1]=(col2[rt<<1|1]+col2[rt])%P; 48 sum[rt<<1|1]=((ll)col2[rt]*(r-(l+r>>1))%P+sum[rt<<1|1])%P; 49 col2[rt]=0; 50 } 51 } 52 void Mul(int l,int r,int rt,int L,int R,int x){ 53 if(l>=L&&r<=R){ 54 col1[rt]=(ll)col1[rt]*x%P; 55 col2[rt]=(ll)col2[rt]*x%P; 56 sum[rt]=(ll)sum[rt]*x%P; 57 return; 58 } 59 Pushdown(rt,l,r); 60 int mid=l+r>>1; 61 if(L<=mid) Mul(lson,L,R,x); 62 if(R>mid) Mul(rson,L,R,x); 63 Pushup(rt); 64 } 65 void Add(int l,int r,int rt,int L,int R,int x){ 66 if(l>=L&&r<=R){ 67 col2[rt]=(col2[rt]+x)%P; 68 sum[rt]=((ll)(r-l+1)*x%P+sum[rt])%P; 69 return; 70 } 71 Pushdown(rt,l,r); 72 int mid=l+r>>1; 73 if(L<=mid) Add(lson,L,R,x); 74 if(R>mid) Add(rson,L,R,x); 75 Pushup(rt); 76 } 77 int Qry(int l,int r,int rt,int L,int R){ 78 if(l>=L&&r<=R) return sum[rt]; 79 Pushdown(rt,l,r); 80 int mid=l+r>>1,ret=0; 81 if(L<=mid) ret=Qry(lson,L,R); 82 if(R>mid) ret=(ret+Qry(rson,L,R))%P; 83 return ret; 84 } 85 int main(){ 86 N=readint(); 87 P=readint(); 88 Build(1,N,1); 89 M=readint(); 90 for(int i=1;i<=M;i++){ 91 int opt=readint(),t,g,c; 92 switch(opt){ 93 case 1: 94 t=readint(); 95 g=readint(); 96 c=readint()%P; 97 Mul(1,N,1,t,g,c); 98 break; 99 case 2: 100 t=readint(); 101 g=readint(); 102 c=readint()%P; 103 Add(1,N,1,t,g,c); 104 break; 105 case 3: 106 t=readint(); 107 g=readint(); 108 outint(Qry(1,N,1,t,g)); 109 putchar('\n'); 110 break; 111 } 112 } 113 return 0; 114 }