【洛谷 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 }

 

posted @ 2016-11-17 10:48  konjac蒟蒻  阅读(183)  评论(0编辑  收藏  举报