hdu4578 线段树多种操作
hdu4578 Transformation
传送门
题意
有一个长度为\(n(1\leq n\leq 100000)\),初始值全为\(0\)的序列\(a\)。给出\(m(1\leq m\leq 100000)\)种操作或者询问:
\(1:\)将区间\([x,y]\)中的值全部加上\(c\)
\(2:\)将区间\([x,y]\)中的值全部乘上\(c\)
\(3:\)将区间\([x,y]\)中的值全部替换成\(c\)
\(4:\)询问区间\([x,y]\)的\(p\)次方和\((a_1^p+a_2^p+a_3^p+\cdots+a_n^p)\),其中\(1\leq p\leq 3\)
题解
由于\(p\)有三个取值\(1,2,3\),所以需要三个数组\(sum1,sum2,sum3\)。\(sum1\)表示一次方和,\(sum2\)表示二次方和,\(sum3\)表示三次方和
三个标记\(add,mul,alt\)分别代表三种操作,\(add\)是加法标记,\(mul\)是乘法标记,\(alt\)是替换标记
标记下放\((pushdown)\)时,\(alt\)的优先级第一,\(mul\)第二,\(add\)第三
在为区间打上高优先级的标记时,会影响到低优先级的标记
在为区间打上\(add\)标记时,\(sum1,sum2,sum3\)的更新顺序为\(sum3,sum2,sum1\),计算方法为:
\((a+x)^3=a^3+3a^2x+3ax^2+x^3\)
\((a_1+x)^3+(a_2+x)^3+\cdots+(a_n+x)^3=(a_1^3+a_2^3+\cdots+a_n^3)+3x(a_1^2+a_2^2+\cdots+a_n^2)+3x^2(a_1+a_2+\cdots+a_n)+nx^3\)
\((a+x)^2=a^2+2ax+x^2\)
\((a_1+x)^2+(a_2+x)^2+\cdots+(a_n+x)^2=(a_1^2+a_2^2+\cdots+a_n^2)+2x(a_1+a_2+\cdots+a_n)+nx^2\)
\((a_1+x)+(a_2+x)+\cdots+(a_n+x)=(a_1+a_2+\cdots+a_n)+n*x\)
#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lowbit(x) (x&(-x))
using namespace std;
const int maxn=100010,mod=10007;
int n,m;
LL sum1[4*maxn],sum2[4*maxn],sum3[4*maxn],add[4*maxn],mul[4*maxn],alt[4*maxn];
void update_add(int o,int l,int r,LL x){
x%=mod;
sum3[o]=(((sum3[o]+3*x%mod*sum2[o]%mod)%mod+3*x%mod*x%mod*sum1[o]%mod)%mod+(r-l+1)%mod*x%mod*x%mod*x%mod)%mod;
sum2[o]=((sum2[o]+2*x%mod*sum1[o]%mod)%mod+(r-l+1)%mod*x%mod*x%mod)%mod;
sum1[o]=(sum1[o]+(r-l+1)%mod*x%mod)%mod;
add[o]=(add[o]+x)%mod;
}
void update_mul(int o,int l,int r,LL x){
x%=mod;
sum1[o]=sum1[o]*x%mod;
sum2[o]=sum2[o]*x%mod*x%mod;
sum3[o]=sum3[o]*x%mod*x%mod*x%mod;
add[o]=add[o]*x%mod;
mul[o]=mul[o]*x%mod;
}
void update_alt(int o,int l,int r,LL x){
x%=mod;
sum1[o]=(r-l+1)%mod*x%mod;
sum2[o]=(r-l+1)%mod*x%mod*x%mod;
sum3[o]=(r-l+1)%mod*x%mod*x%mod*x%mod;
add[o]=0;
mul[o]=1;
alt[o]=x;
}
void pushup(int o){
sum1[o]=(sum1[o<<1]+sum1[o<<1|1])%mod;
sum2[o]=(sum2[o<<1]+sum2[o<<1|1])%mod;
sum3[o]=(sum3[o<<1]+sum3[o<<1|1])%mod;
}
void pushdown(int o,int l,int r){
int mid=(l+r)>>1;
if(alt[o]){
update_alt(lson,alt[o]);
update_alt(rson,alt[o]);
alt[o]=0;
}
if(mul[o]!=1){
update_mul(lson,mul[o]);
update_mul(rson,mul[o]);
mul[o]=1;
}
if(add[o]){
update_add(lson,add[o]);
update_add(rson,add[o]);
add[o]=0;
}
}
void build(int o,int l,int r){
add[o]=alt[o]=0;
mul[o]=1;
sum1[o]=sum2[o]=sum3[o]=0;
if(l==r){
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(o);
}
void Add(int o,int l,int r,int ql,int qr,LL x){
if(ql<=l && r<=qr){
update_add(o,l,r,x);
return;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(ql<=mid) Add(lson,ql,qr,x);
if(qr>mid) Add(rson,ql,qr,x);
pushup(o);
}
void Mul(int o,int l,int r,int ql,int qr,LL x){
if(ql<=l && r<=qr){
update_mul(o,l,r,x);
return;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(ql<=mid) Mul(lson,ql,qr,x);
if(qr>mid) Mul(rson,ql,qr,x);
pushup(o);
}
void Alt(int o,int l,int r,int ql,int qr,LL x){
if(ql<=l && r<=qr){
update_alt(o,l,r,x);
return;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(ql<=mid) Alt(lson,ql,qr,x);
if(qr>mid) Alt(rson,ql,qr,x);
pushup(o);
}
LL query(int o,int l,int r,int ql,int qr,LL p){
if(ql<=l && r<=qr){
if(p==1) return sum1[o];
if(p==2) return sum2[o];
if(p==3) return sum3[o];
}
pushdown(o,l,r);
int mid=(l+r)>>1;
LL ans=0;
if(ql<=mid) ans=(ans+query(lson,ql,qr,p))%mod;
if(qr>mid) ans=(ans+query(rson,ql,qr,p))%mod;
return ans;
}
int main(){
while(scanf("%d %d",&n,&m)!=EOF){
if(n==0 && m==0) break;
build(1,1,n);
for(int i=1;i<=m;i++){
int op,x,y;
LL c;
scanf("%d %d %d %lld",&op,&x,&y,&c);
if(op==1){
Add(1,1,n,x,y,c);
}
else if(op==2){
Mul(1,1,n,x,y,c);
}
else if(op==3){
Alt(1,1,n,x,y,c);
}
else{
printf("%lld\n",query(1,1,n,x,y,c));
}
}
}
}