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));
			}
		}
	}
}
posted @ 2020-10-09 22:57  fxq1304  阅读(30)  评论(0编辑  收藏  举报