HDU4578-Transformation (線段樹多種區間操作)
阿新 • • 發佈:2018-12-16
題意:一開始有n個為0的數,一共有四種操作:區間[l,r]內的數全部加c。區間[l,r]內的數全部乘c。區間[l,r]內的數全部初始為c。詢問區間[l,r]內所有數的P次方之和。
分析:因為操作種數較多,不可能遞迴到底層然後進行計算,只需判斷這個區間的元素是否完全相同,然後直接進行計算即可。
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int mod=10007; int x[maxn<<2]; bool flag[maxn<<2]; //判斷以i為節點的區間的值是否是相同的。 inline void update(int i){ if(!flag[i]) return; flag[i<<1]=flag[i<<1|1]=1; x[i<<1]=x[i<<1|1]=x[i]; flag[i]=0; } inline void Union(int i){ if(!flag[i<<1]||!flag[i<<1|1]) flag[i]=0; else if(x[i<<1]!=x[i<<1|1]) flag[i]=0; else flag[i]=1,x[i]=x[i<<1]; } void change(int tl,int tr,int l,int r,int i,int v,int type){ if(tl>r||tr<l) return; if(tl<=l&&r<=tr&&flag[i]){ if(type==1){ x[i]=(x[i]%mod+v%mod)%mod; }else if(type==2){ x[i]=x[i]%mod*v%mod; }else{ x[i]=v%mod; } return; } update(i); int mid=l+r>>1; change(tl,tr,l,mid,i<<1,v,type); change(tl,tr,mid+1,r,i<<1|1,v,type); Union(i); } int query(int tl,int tr,int l,int r,int i,int v){ if(tl>r||tr<l) return 0; if(tl<=l&&r<=tr&&flag[i]){ int sum=1; for(int j=1;j<=v;j++) sum=sum%mod*x[i]%mod; sum=sum*(r-l+1)%mod; return sum; } update(i); int mid=l+r>>1; return (query(tl,tr,l,mid,i<<1,v)+query(tl,tr,mid+1,r,i<<1|1,v))%mod; } int main(){ int n,m; while(scanf("%d%d",&n,&m)&&(n||m)){ memset(x,0,sizeof x); memset(flag,1,sizeof flag); while(m--){ int f,l,r,v; scanf("%d%d%d%d",&f,&l,&r,&v); if(f==4){ printf("%d\n",query(l,r,1,n,1,v)); }else{ change(l,r,1,n,1,v,f); } } } return 0; }