【洛谷 p3373】模板-线段树 2(数据结构--线段树)
题意:已知一个数列,你需要进行下面三种操作:1.将某区间每一个数加上x;2.将某区间每一个数乘上x;3.求出某区间每一个数的和。
解法:(唉 :-(,这题卡住我了......)对于加法和乘法的混合操作,lazy 标记记为 add , mul。
我们可以把运算全部化为 x*mul+add*(r-l+1) 的模型,其中它的运算有2种情况:
1.当前为加法,(x*mul+add*(r-l+1))+add'*(r-l+1) → (x*mul)+(add+add')*(r-l+1),也就是 add+=add';
2.当前为乘法,(x*mul+add*(r-l+1))*mul' → (x*mul*mul')+(add*(r-l+1)*mul'),也就是 mul*=mul', add*=mul'。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define N 100010 7 typedef long long LL; 8 9 int n,m,P,len=0; 10 struct node 11 { 12 int l,r,lc,rc; 13 LL d,mul,add; 14 }a[2*N]; 15 16 void build(int l,int r) 17 { 18 int x=++len; 19 a[x].l=l,a[x].r=r,a[x].d=0; 20 a[x].lc=a[x].rc=-1; 21 a[x].mul=1,a[x].add=0; 22 if (l<r) 23 { 24 int mid=(l+r)>>1; 25 a[x].lc=len+1,build(l,mid); 26 a[x].rc=len+1,build(mid+1,r); 27 } 28 } 29 void Pdown(int x,LL mul,LL add) 30 { 31 a[x].d=((a[x].d*mul)%P+(add*(a[x].r-a[x].l+1)%P))%P;//r-l+1 32 a[x].mul=(a[x].mul*mul)%P; 33 a[x].add=((a[x].add*mul)%P+add)%P; 34 } 35 void updata(int x) 36 { 37 if (a[x].mul==1 && !a[x].add) return; 38 int lc=a[x].lc,rc=a[x].rc; 39 if (lc!=-1) Pdown(lc,a[x].mul,a[x].add); 40 if (rc!=-1) Pdown(rc,a[x].mul,a[x].add); 41 a[x].mul=1,a[x].add=0; 42 } 43 void addi(int x,int l,int r,LL d) 44 { 45 if (a[x].l==l && a[x].r==r) 46 { 47 a[x].d=(a[x].d+d*(r-l+1))%P;//r-l+1 48 a[x].add=(a[x].add+d)%P; 49 return; 50 } 51 updata(x); 52 int lc=a[x].lc,rc=a[x].rc,mid=(a[x].l+a[x].r)>>1; 53 if (r<=mid) addi(lc,l,r,d); 54 else if (l>mid) addi(rc,l,r,d); 55 else addi(lc,l,mid,d),addi(rc,mid+1,r,d); 56 a[x].d=(a[lc].d+a[rc].d)%P;//only d 57 } 58 void multi(int x,int l,int r,LL d) 59 { 60 if (a[x].l==l && a[x].r==r) 61 { 62 a[x].d=(a[x].d*d)%P; 63 a[x].mul=(a[x].mul*d)%P,a[x].add=(a[x].add*d)%P; 64 return; 65 } 66 updata(x); 67 int lc=a[x].lc,rc=a[x].rc,mid=(a[x].l+a[x].r)>>1; 68 if (r<=mid) multi(lc,l,r,d); 69 else if (l>mid) multi(rc,l,r,d); 70 else multi(lc,l,mid,d),multi(rc,mid+1,r,d); 71 a[x].d=(a[lc].d+a[rc].d)%P; 72 } 73 LL query(int x,int l,int r) 74 { 75 updata(x); 76 if (a[x].l==l && a[x].r==r) return a[x].d; 77 int lc=a[x].lc,rc=a[x].rc,mid=(a[x].l+a[x].r)>>1; 78 if (r<=mid) return query(lc,l,r)%P;//%P 79 else if (l>mid) return query(rc,l,r)%P; 80 else return (query(lc,l,mid)+query(rc,mid+1,r))%P; 81 } 82 int main() 83 { 84 LL d; int x,y,k; 85 scanf("%d%d%d",&n,&m,&P); 86 build(1,n); 87 for (int i=1;i<=n;i++) 88 { 89 scanf("%lld",&d); 90 addi(1,i,i,d); 91 } 92 while (m--) 93 { 94 scanf("%d%d%d",&k,&x,&y); 95 if (x>y) {int t;t=x,x=y,y=t;} 96 if (k==1) 97 { 98 scanf("%lld",&d); 99 multi(1,x,y,d%P); 100 } 101 else if (k==2) 102 { 103 scanf("%lld",&d); 104 addi(1,x,y,d%P); 105 } 106 else printf("%lld\n",query(1,x,y)); 107 } 108 return 0; 109 }