HDU 4578 Transformation 线段树
三个标记,注意到乘法标记会影响加法标记,然后就是一般的成段更新了。
AC后搜别人的题解发现原来替换标记可以用一个乘0和加c代替,这样就不用三个标记了。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<sstream> #include<cmath> #include<climits> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define pb(a) push_back(a) #define INF 0x1f1f1f1f #define lson idx<<1,l,mid #define rson idx<<1|1,mid+1,r #define PI 3.1415926535898 template<class T> T min(const T& a,const T& b,const T& c) { return min(min(a,b),min(a,c)); } template<class T> T max(const T& a,const T& b,const T& c) { return max(max(a,b),max(a,c)); } void debug() { #ifdef ONLINE_JUDGE #else freopen("d:\\in.txt","r",stdin); // freopen("d:\\out1.txt","w",stdout); #endif } int getch() { int ch; while((ch=getchar())!=EOF) { if(ch!=' '&&ch!='\n')return ch; } return EOF; } const int maxn=100100; const int mod=10007; struct Tree { int sum[maxn<<2][3]; int mul[maxn<<2],add[maxn<<2],setv[maxn<<2]; void setv_(int idx,int len,int v) { int x=v; for(int i=0;i<3;i++) { sum[idx][i]=x*len%mod; x=x*v%mod; } setv[idx]=v; mul[idx]=1; add[idx]=0; } void add_(int idx,int len,int v) { sum[idx][2]=(sum[idx][2]+3*sum[idx][1]*v%mod+3*sum[idx][0]*v%mod*v%mod+v%mod*v%mod*v%mod*len%mod)%mod; sum[idx][1]=(sum[idx][1]+2*sum[idx][0]*v%mod+v*v%mod*len%mod)%mod; sum[idx][0]=(sum[idx][0]+v*len%mod)%mod; add[idx]=(add[idx]+v)%mod; } void mul_(int idx,int len,int v) { sum[idx][2]=sum[idx][2]*v%mod*v%mod*v%mod; sum[idx][1]=sum[idx][1]*v%mod*v%mod; sum[idx][0]=sum[idx][0]*v%mod; mul[idx]=mul[idx]*v%mod; add[idx]=add[idx]*v%mod; } void PushUp(int idx) { for(int i=0;i<3;i++) sum[idx][i]=(sum[idx<<1][i]+sum[idx<<1|1][i])%mod; } void PushDown(int idx,int l,int r) { int mid=(r+l)>>1; if(setv[idx]!=-1) { setv_(idx<<1,mid-l+1,setv[idx]); setv_(idx<<1|1,r-mid,setv[idx]); setv[idx]=-1; } if(mul[idx]!=1) { mul_(idx<<1,mid-l+1,mul[idx]); mul_(idx<<1|1,r-mid,mul[idx]); mul[idx]=1; } if(add[idx]!=0) { add_(idx<<1,mid-l+1,add[idx]); add_(idx<<1|1,r-mid,add[idx]); add[idx]=0; } } void build(int idx,int l,int r) { setv[idx]=-1; mul[idx]=1; add[idx]=0; sum[idx][0]=sum[idx][1]=sum[idx][2]=0; if(l==r)return ; int mid=(r+l)>>1; build(lson); build(rson); } int update(int idx,int l,int r,int tl,int tr,int op,int v) { if(tl<=l&&tr>=r) { if(op==1) add_(idx,r-l+1,v); else if(op==2) mul_(idx,r-l+1,v); else setv_(idx,r-l+1,v); return 0; } PushDown(idx,l,r); int mid=(r+l)>>1; if(tl<=mid)update(lson,tl,tr,op,v); if(tr>mid)update(rson,tl,tr,op,v); PushUp(idx); return 0; } int query(int idx,int l,int r,int tl,int tr,int p) { if(tl<=l&&tr>=r) return sum[idx][p-1]; PushDown(idx,l,r); int mid=(r+l)>>1; int x=0; if(tl<=mid)x=(x+query(lson,tl,tr,p))%mod; if(tr>mid)x=(x+query(rson,tl,tr,p))%mod; return x; } }; Tree tree; int main() { debug(); int n,m; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)) { tree.build(1,1,n); for(int i=1;i<=m;i++) { int op,a,b,v; scanf("%d%d%d%d",&op,&a,&b,&v); if(op==4) printf("%d\n",tree.query(1,1,n,a,b,v)); else tree.update(1,1,n,a,b,op,v); } } return 0; }