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 }