线段树
//线段树区间/单点加、减、乘、赋值,查询区间/单点和、最大值、最小值。 #include<cstdio> #include<cctype> #include<algorithm> using namespace std; namespace IO { const int InputBufferSize = 48*1024*1024; const int OutputBufferSize = 48*1024*1024; namespace input { char buffer[InputBufferSize],*s,*eof; inline void init() { s=buffer; eof=s+fread(buffer,1,InputBufferSize,stdin); } inline bool read(long long &x) { x=0; int flag=1; while(!isdigit(*s)&&*s!='-') s++; if(eof<=s) return false; if(*s=='-') { flag=-1; s++; } while(isdigit(*s)) x=x*10+*s++-'0'; x*=flag; return true; } inline bool read(int &x) { x=0; int flag=1; while(!isdigit(*s)&&*s!='-') s++; if(eof<=s) return false; if(*s=='-') { flag=-1,s++; } while(isdigit(*s)) x=x*10+*s++-'0'; x*=flag; return true; } inline bool read(char *str) { *str=0; while(isspace(*s)) s++; if(eof<s) return false; while(!isspace(*s)) { *str=0; *str=*s; str++; s++; } *str=0; return true; } inline bool read(char &ch) { ch=0; while(isspace(*s)) s++; if(eof<s) return false; ch=0; ch=*s; s++; return true; } } namespace output { char buffer[OutputBufferSize]; char *s=buffer; inline void flush() { fwrite(buffer,1,s-buffer,stdout); s=buffer; } inline void print(const char ch) { if(s-buffer>OutputBufferSize-2) flush(); *s++=ch; } inline void print(char *str) { while(*str!=0) print(char(*str++)); } inline void print(long long x) { char buf[25]= {0},*p=buf; if(x<0) { print('-'); x=-x; } if(x==0) print('0'); while(x) { *(++p)=x%10; x/=10; } while(p!=buf) print(char(*(p--)+'0')); } inline void print(int x) { char buf[25]= {0},*p=buf; if(x<0) { print('-'); x=-x; } if(x==0) print('0'); while(x) { *(++p)=x%10; x/=10; } while(p!=buf) print(char(*(p--)+'0')); } } using namespace input; using namespace output; } using namespace IO; namespace SegmentTree { #define mid ((l+r)>>1) #define lson (o<<1) #define rson (lson|1) long long p; long long sum[800010]; long long addv[800010]; long long mulv[800010]; long long Min[800010]; long long Max[800010]; long long chav[800010]; bool c[800010]; inline void push_up(int o) { sum[o]=(sum[lson]+sum[rson])%p; Min[o]=(min(Min[lson],Min[rson]))%p; Max[o]=(max(Max[lson],Max[rson]))%p; } void build(int o,int l,int r) { addv[o]=0; mulv[o]=1; chav[o]=0; c[o]=false; if(l==r) { read(sum[o]); Min[o]=sum[l]; Max[o]=sum[l]; return; } build(lson,l,mid); build(rson,mid+1,r); push_up(o); } inline void push_down(int o,int l,int r,int mi,int ls,int rs) { if(c[o]) { mulv[ls]=1; mulv[rs]=1; addv[ls]=0; addv[rs]=0; sum[ls]=((mi-l+1)*chav[ls])%p; sum[rs]=((r-mi)*chav[rs])%p; Min[ls]=chav[o]; Min[rs]=chav[o]; Max[ls]=chav[o]; Max[rs]=chav[o]; chav[o]=0; c[o]=false; } if(mulv[o]!=1) { mulv[ls]=(mulv[ls]*mulv[o])%p; mulv[rs]=(mulv[rs]*mulv[o])%p; addv[ls]=(addv[ls]*mulv[o])%p; addv[rs]=(addv[rs]*mulv[o])%p; sum[ls]=(sum[ls]*mulv[o])%p; sum[rs]=(sum[rs]*mulv[o])%p; Min[ls]=(Min[ls]*mulv[o])%p; Min[rs]=(Min[rs]*mulv[o])%p; Max[ls]=(Max[ls]*mulv[o])%p; Max[rs]=(Max[rs]*mulv[o])%p; mulv[o]=1; } if(addv[o]!=0) { addv[ls]=(addv[ls]+addv[o])%p; addv[rs]=(addv[rs]+addv[o])%p; sum[ls]=(sum[ls]+(mi-l+1)*addv[o])%p; sum[rs]=(sum[rs]+(r-mi)*addv[o])%p; Min[ls]=(Min[ls]+addv[o])%p; Min[rs]=(Min[rs]+addv[o])%p; Max[ls]=(Max[ls]+addv[o])%p; Max[rs]=(Max[rs]+addv[o])%p; addv[o]=0; } } void addall(int o,int l,int r,int a,int b,int x) { if(l>=a&&r<=b) { addv[o]=(addv[o]+x)%p; sum[o]=(sum[o]+(r-l+1)*x)%p; return; } push_down(o,l,r,mid,lson,rson); if(a<=mid) addall(lson,l,mid,a,b,x); if(b>mid) addall(rson,mid+1,r,a,b,x); push_up(o); } void mulall(int o,int l,int r,int a,int b,int x) { if(l>=a&&r<=b) { mulv[o]=(mulv[o]*x)%p; addv[o]=(addv[o]*x)%p; sum[o]=(sum[o]*x)%p; return; } push_down(o,l,r,mid,lson,rson); if(a<=mid) mulall(lson,l,mid,a,b,x); if(b>mid) mulall(rson,mid+1,r,a,b,x); push_up(o); } void chaall(int o,int l,int r,int a,int b,int x) { if(l>=a&&r<=b) { chav[o]=x%p; sum[o]=x*(r-l+1)%p; Max[o]=x%p; Min[o]=x%p; addv[o]=0; mulv[o]=1; c[o]=true; return; } push_down(o,l,r,mid,lson,rson); if(a<=mid) chaall(lson,l,mid,a,b,x); if(b>mid) chaall(rson,mid+1,r,a,b,x); push_up(o); } long long querySum(int o,int l,int r,int a,int b) { if(l>=a&&r<=b) return sum[o]%p; long long ans=0; push_down(o,l,r,mid,lson,rson); if(a<=mid) ans+=querySum(lson,l,mid,a,b); if(b>mid) ans+=querySum(rson,mid+1,r,a,b); return ans%p; } long long queryMax(int o,int l,int r,int a,int b) { if(l>=a&&r<=b) return Max[o]%p; long long ans=0; push_down(o,l,r,mid,lson,rson); if(a<=mid) ans=max(ans,queryMax(lson,l,mid,a,b)); if(b>mid) ans=max(ans,queryMax(rson,mid+1,r,a,b)); return ans%p; } long long queryMin(int o,int l,int r,int a,int b) { if(l>=a&&r<=b) return Min[o]%p; long long ans=0x7fffffffffffffff; push_down(o,l,r,mid,lson,rson); if(a<=mid) ans=min(ans,queryMin(lson,l,mid,a,b)); if(b>mid) ans=min(ans,queryMin(rson,mid+1,r,a,b)); return ans%p; } #undef mid #undef lson #undef rson } using namespace SegmentTree; int n,m,i,f; int x,y; long long k; int main() { #ifdef LOCAL freopen("data.in","rb",stdin); #endif init(); read(n),read(m),read(p); build(1,1,n); while(m--) { read(f); switch(f) { case 1: read(x); read(y); read(k); mulall(1,1,n,x,y,k); break; case 2: read(x); read(y); read(k); addall(1,1,n,x,y,k); break; case 3: read(x); read(y); print(querySum(1,1,n,x,y)),print('\n'); break; case 4: read(x); read(y); read(k); chaall(1,1,n,x,y,k); break; } } flush(); return 0; }