HDU - 4578 Transformation
题 意:给你n个数字,开始都是0,m次操作,1 x y p:区间[x,y]每个数都加上p。2 x y c
:区间[x,y]全部都乘p,3 x y c.将区间[x,y]的值全部都设为c。4 x y p,查询[x,y]所有值的p次方和。
数据范围:
1<=n,m<=1e5
1<=c<=1e4
x,y<=n
1<=p<=3
输入样例:
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
输出样例:
307
7489
思 路:用三个懒惰标记add,mul,set。注意懒惰标记pushdown的次序。
收 获:学会了set,mul,add的懒惰标记的打法。以及混和的打法
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
const int mod = 10007;
ll add[maxn<<2],mul[maxn<<2],se[maxn<<2];
ll sum1[maxn<<2],sum2[maxn<<2],sum3[maxn<<2];
int n,m;
void PushUp(int rt){
sum1[rt] = (sum1[rt<<1] + sum1[rt<<1|1])%mod;
sum2[rt] = (sum2[rt<<1] + sum2[rt<<1|1])%mod;
sum3[rt] = (sum3[rt<<1] + sum3[rt<<1|1])%mod;
}
void build(int l,int r,int rt){
add[rt] = se[rt] = 0;
mul[rt] = 1;
if(l == r){
sum1[rt] = sum2[rt] = sum3[rt] = 0;
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void PushDown(int rt,int len){
if(se[rt]){
add[rt<<1|1] = add[rt<<1] = 0;
mul[rt<<1|1] = mul[rt<<1] = 1;
se[rt<<1] = se[rt<<1|1] = se[rt];
sum3[rt<<1] = ((((((len-(len>>1))*se[rt]%mod)%mod)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
sum3[rt<<1|1] = ((((((len>>1)*se[rt]%mod)%mod)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
sum2[rt<<1] = ((((len-(len>>1))*se[rt]%mod)%mod)*se[rt]%mod)%mod;
sum2[rt<<1|1] = ((((len>>1)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
sum1[rt<<1] = ((len-(len>>1))*se[rt]%mod)%mod;
sum1[rt<<1|1] = ((len>>1)*se[rt]%mod)%mod;
se[rt] = 0;
}
if(mul[rt]!=1){
if(add[rt<<1]){
add[rt<<1] = (add[rt<<1]*mul[rt])%mod;
}
if(add[rt<<1|1]){
add[rt<<1|1] = (add[rt<<1|1]*mul[rt])%mod;
}
mul[rt<<1] =(mul[rt]*mul[rt<<1])%mod;
mul[rt<<1|1] =(mul[rt<<1|1] * mul[rt])%mod;
sum3[rt<<1] = (((((((sum3[rt<<1])%mod)*mul[rt])%mod)*mul[rt])%mod)*mul[rt])%mod;
sum3[rt<<1|1] = (((((sum3[rt<<1|1]*mul[rt]%mod)%mod)*mul[rt])%mod)*mul[rt])%mod;
sum2[rt<<1] = (((sum2[rt<<1]*mul[rt]%mod)%mod)*mul[rt])%mod;
sum2[rt<<1|1] = (((sum2[rt<<1|1]*mul[rt])%mod)*mul[rt])%mod;
sum1[rt<<1] = (sum1[rt<<1]*mul[rt])%mod;
sum1[rt<<1|1] = (sum1[rt<<1|1]*mul[rt])%mod;
mul[rt] = 1;
}
if(add[rt]){
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
int tmp = (((((add[rt])%mod)*add[rt])%mod)*add[rt])%mod;
sum3[rt<<1] = ((sum3[rt<<1]+ (tmp*(len-(len>>1)))%mod + ((3*add[rt])%mod)*(sum2[rt<<1]+sum1[rt<<1]*add[rt])%mod))%mod;
sum3[rt<<1|1] = (sum3[rt<<1|1] + (tmp*(len>>1))%mod + ((3*add[rt])%mod)*(sum2[rt<<1|1]+sum1[rt<<1|1]*add[rt])%mod)%mod;
sum2[rt<<1] = (sum2[rt<<1] + (((len-(len>>1))*add[rt]%mod)*add[rt]%mod) + (2*add[rt]*sum1[rt<<1])%mod)%mod;
sum2[rt<<1|1] = (sum2[rt<<1|1] + ((((len>>1))*add[rt]%mod)*add[rt]%mod) + (2*add[rt]*sum1[rt<<1|1])%mod)%mod;
sum1[rt<<1] = (sum1[rt<<1] + ((len - (len>>1))*add[rt])%mod)%mod;
sum1[rt<<1|1] = (sum1[rt<<1|1] + ((len>>1)*add[rt])%mod)%mod;
add[rt] = 0;
}
}
void update(int L,int R,int x,int p,int l,int r,int rt){
if(L<=l && r<=R){
if(p == 3){
se[rt] = x;
mul[rt] = 1;
add[rt] = 0;
sum3[rt] = ((((((r-l+1)*x)%mod)*x)%mod)*x)%mod;
sum2[rt] = (((r-l+1)*x%mod)*x%mod)%mod;
sum1[rt] = ((r-l+1)*x)%mod;
}else if(p==2){
mul[rt]=(x*mul[rt])%mod;
if(add[rt]){
add[rt] = (add[rt]*x)%mod;
}
sum3[rt] = ((((((sum3[rt]%mod)*x)%mod)*x)%mod)*x)%mod;
sum2[rt] = (((sum2[rt]*x)%mod)*x)%mod;
sum1[rt] = (sum1[rt]*x)%mod;
}else if(p == 1){
add[rt]+=x;
sum3[rt] = (sum3[rt] + ((((((r-l+1)*x)%mod)*x)%mod)*x)%mod +((3*x)%mod)*(sum2[rt] + (sum1[rt]*x)%mod))%mod;
sum2[rt] = (sum2[rt]+((((r-l+1)*x)%mod)*x)%mod + 2*x*sum1[rt]%mod)%mod;
sum1[rt] = (sum1[rt] + ((r-l+1)*x)%mod)%mod;
}
return ;
}
PushDown(rt,r-l+1);
int m = (l+r)/2;
if(L<=m) update(L,R,x,p,lson);
if(R>m) update(L,R,x,p,rson);
PushUp(rt);
}
ll query(int L,int R,int p,int l,int r,int rt){
if(L <= l && r<=R){
if(p==1){
return sum1[rt]%mod;
}else if(p == 2){
return sum2[rt]%mod;
}else{
return sum3[rt]%mod;
}
}
PushDown(rt,r-l+1);
int m = (l+r)>>1,ans = 0;
if(L<=m) ans=(ans+query(L,R,p,lson))%mod;
if(R>m) ans=(ans+query(L,R,p,rson))%mod;
return ans;
}
int main(){
while(~scanf("%d %d",&n,&m) && (n+m)){
build(1,n,1);
int a,l,r,p;
for(int i=0;i<m;i++){
scanf("%d %d %d %d",&a,&l,&r,&p);
if(a != 4){
update(l,r,p,a,1,n,1);
}else{
ll ans = query(l,r,p,1,n,1);
printf("%lld\n",ans);
}
}
}
return 0;
}
/*
2
6 2 4
*/