1. 程式人生 > >bzoj 1798 [Ahoi2009]Seq 維護序列seq ——線段樹

bzoj 1798 [Ahoi2009]Seq 維護序列seq ——線段樹

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1798

先乘後加,就可給加法標記乘上乘法標記。

注意可能有 *0 的操作,所以 pshd 時不是 cg[ cr ]>1 而是 cg[ cr ]!=1 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define ls Ls[cr]
#define rs Rs[cr]
using namespace
std; const int N=1e5+5,M=N<<1; int n,m,mod,a[N],Ls[M],Rs[M],cg[M],jg[M],sm[M],tot; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return
fx?ret:-ret; } int g[20]; void wrt(int x) { if(x<0)putchar('-'),x=-x; if(!x){puts("0");return;} int t=0;while(x)g[++t]=x%10,x/=10; while(t)putchar(g[t]+'0'),t--;puts(""); } void upd(int &x){x>=mod?x-=mod:0;} void pshp(int cr){sm[cr]=sm[ls]+sm[rs];upd(sm[cr]);} void build(int l,int r,int cr) { cg[cr]
=1; if(l==r){sm[cr]=a[l]%mod;return;} int mid=l+r>>1; ls=++tot; build(l,mid,ls); rs=++tot; build(mid+1,r,rs); pshp(cr); } void pshd(int cr,int l,int mid,int r) { if(cg[cr]!=1) { int w=cg[cr]; cg[cr]=1; cg[ls]=(ll)cg[ls]*w%mod; cg[rs]=(ll)cg[rs]*w%mod; jg[ls]=(ll)jg[ls]*w%mod; jg[rs]=(ll)jg[rs]*w%mod; sm[ls]=(ll)sm[ls]*w%mod; sm[rs]=(ll)sm[rs]*w%mod; } if(jg[cr]) { int w=jg[cr]; jg[cr]=0; jg[ls]+=w;upd(jg[ls]); jg[rs]+=w;upd(jg[rs]); sm[ls]=(sm[ls]+(ll)(mid-l+1)*w)%mod; sm[rs]=(sm[rs]+(ll)(r-mid)*w)%mod; } } void mdfy(int l,int r,int cr,int L,int R,int k,bool fx) { if(l>=L&&r<=R) { if(!fx) cg[cr]=(ll)cg[cr]*k%mod, sm[cr]=(ll)sm[cr]*k%mod, jg[cr]=(ll)jg[cr]*k%mod; else jg[cr]+=k,upd(jg[cr]),sm[cr]=(sm[cr]+(ll)(r-l+1)*k)%mod; return; } int mid=l+r>>1; pshd(cr,l,mid,r); if(L<=mid)mdfy(l,mid,ls,L,R,k,fx); if(mid<R)mdfy(mid+1,r,rs,L,R,k,fx); pshp(cr); } int query(int l,int r,int cr,int L,int R) { if(l>=L&&r<=R)return sm[cr]; int mid=l+r>>1,ret=0; pshd(cr,l,mid,r); if(L<=mid)ret=query(l,mid,ls,L,R); if(mid<R)ret+=query(mid+1,r,rs,L,R),upd(ret); return ret; } int main() { n=rdn(); mod=rdn(); for(int i=1;i<=n;i++)a[i]=rdn(); tot=1; build(1,n,1); m=rdn(); for(int i=1,op,l,r,k;i<=m;i++) { op=rdn();l=rdn();r=rdn(); if(op==1) { k=rdn()%mod;mdfy(1,n,1,l,r,k,0); } if(op==2) { k=rdn()%mod;mdfy(1,n,1,l,r,k,1); } if(op==3) wrt(query(1,n,1,l,r)); } return 0; }