bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树)

1798: [Ahoi2009]Seq 维护序列seq

题目:传送门


 

题解:

   好题!毒瘤恶心题!

   有打过线段树lazy的经验之后其实并不难,也就加niang个lazy标记死磕代码咯

   吐槽:update先加后乘WA...反过来...A了


代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 typedef long long LL;
  8 struct trnode
  9 {
 10     int l,r,lc,rc;LL sum;
 11     LL lzj,lzc;//lazy 有标记则表示自己已经改了但是管理的区间没改 
 12 }tr[410000];int trlen,n,m,mod;
 13 int a[410000];
 14 void bt(int l,int r)
 15 {
 16     int now=++trlen;
 17     tr[now].l=l;tr[now].r=r;
 18     if(l==r)
 19     {
 20         tr[now].lc=tr[now].rc=0;
 21         tr[now].sum=a[l];tr[now].lzj=0;tr[now].lzc=1;
 22     }
 23     else
 24     {
 25         int mid=(l+r)/2;
 26         tr[now].lc=trlen+1;bt(l,mid);
 27         tr[now].rc=trlen+1;bt(mid+1,r);
 28         tr[now].sum=(tr[tr[now].lc].sum+tr[tr[now].rc].sum)%mod;
 29         tr[now].lzj=0;tr[now].lzc=1;
 30     }
 31 }
 32 void update(int now)
 33 {
 34     int lc=tr[now].lc,rc=tr[now].rc;
 35     if(tr[now].lzc!=1)
 36     {
 37         tr[lc].sum=(tr[lc].sum*tr[now].lzc)%mod;
 38         tr[lc].lzj=(tr[lc].lzj*tr[now].lzc)%mod;
 39         tr[lc].lzc=(tr[lc].lzc*tr[now].lzc)%mod;
 40         tr[rc].sum=(tr[rc].sum*tr[now].lzc)%mod;
 41         tr[rc].lzj=(tr[rc].lzj*tr[now].lzc)%mod;
 42         tr[rc].lzc=(tr[rc].lzc*tr[now].lzc)%mod;
 43         tr[now].lzc=1;
 44     }
 45     if(tr[now].lzj!=0)
 46     {
 47         int cnt;
 48         cnt=tr[lc].r-tr[lc].l+1;
 49         tr[lc].sum=(tr[lc].sum+cnt*tr[now].lzj)%mod;
 50         tr[lc].lzj=(tr[lc].lzj+tr[now].lzj)%mod;
 51         cnt=tr[rc].r-tr[rc].l+1;
 52         tr[rc].sum=(tr[rc].sum+cnt*tr[now].lzj)%mod;
 53         tr[rc].lzj=(tr[rc].lzj+tr[now].lzj)%mod;
 54         tr[now].lzj=0;
 55     }
 56 }
 57 void add(int now,int l,int r,LL x)
 58 {
 59     if(tr[now].l==l && tr[now].r==r)
 60     {
 61         update(now);
 62         int cnt=r-l+1;
 63         tr[now].sum=(tr[now].sum+cnt*x)%mod;
 64         tr[now].lzj=(tr[now].lzj+x)%mod;
 65         return ;
 66     }
 67     update(now);
 68     int mid=(tr[now].l+tr[now].r)/2,lc=tr[now].lc,rc=tr[now].rc;
 69     if(r<=mid)add(lc,l,r,x);
 70     else if(mid+1<=l)add(rc,l,r,x);
 71     else add(lc,l,mid,x),add(rc,mid+1,r,x);
 72     tr[now].sum=(tr[lc].sum+tr[rc].sum)%mod;
 73 }
 74 void multi(int now,int l,int r,LL x)
 75 {
 76     if(tr[now].l==l && tr[now].r==r)
 77     {
 78         update(now);
 79         tr[now].sum=(tr[now].sum*x)%mod;
 80         tr[now].lzj=(tr[now].lzj*x)%mod;
 81         tr[now].lzc=(tr[now].lzc*x)%mod;
 82         return ;
 83     }
 84     update(now);
 85     int mid=(tr[now].l+tr[now].r)/2,lc=tr[now].lc,rc=tr[now].rc;
 86     if(r<=mid)multi(lc,l,r,x);
 87     else if(mid+1<=l)multi(rc,l,r,x);
 88     else multi(lc,l,mid,x),multi(rc,mid+1,r,x);
 89     tr[now].sum=(tr[lc].sum+tr[rc].sum)%mod;
 90 }
 91 LL getsum(int now,int l,int r)
 92 {
 93     if(tr[now].l==l && tr[now].r==r)return tr[now].sum;
 94     update(now);
 95     int mid=(tr[now].l+tr[now].r)/2,lc=tr[now].lc,rc=tr[now].rc;
 96     if(r<=mid)return getsum(lc,l,r);
 97     else if(mid+1<=l)return getsum(rc,l,r);
 98     else return (getsum(lc,l,mid)+getsum(rc,mid+1,r))%mod;
 99 }
100 int main()
101 {
102     scanf("%d%lld",&n,&mod);for(int i=1;i<=n;i++)scanf("%d",&a[i]);
103     trlen=0;bt(1,n);
104     scanf("%d",&m);
105     for(int i=1;i<=m;i++)
106     {
107         LL x;int Q,l,r;
108         scanf("%d",&Q);
109         if(Q==1)
110         {
111             scanf("%d%d%lld",&l,&r,&x);
112             multi(1,l,r,x%mod);
113         }
114         if(Q==2)
115         {
116             scanf("%d%d%lld",&l,&r,&x);
117             add(1,l,r,x%mod);
118         }
119         if(Q==3)
120         {
121             scanf("%d%d",&l,&r);
122             printf("%lld\n",getsum(1,l,r));
123         }
124     }
125     return 0;
126 }

 

posted @ 2018-03-10 09:27  CHerish_OI  阅读(195)  评论(0编辑  收藏  举报