题意:一开始有n个为0的数,一共有四种操作:区间[l,r]内的数全部加c。区间[l,r]内的数全部乘c。区间[l,r]内的数全部初始为c。询问区间[l,r]内所有数的P次方之和。
分析:因为操作种数较多,不可能递归到底层然后进行计算,只需判断这个区间的元素是否完全相同,然后直接进行计算即可。
参考博客:https://blog.csdn.net/a664607530/article/details/74563018
#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;
}