hdu4578(三个更新操作,三个求值操作)

<span style="widows: auto;"><span style="font-family:KaiTi_GB2312;font-size:18px;">题意:有长为n的数列,初始化为全部为0,我们对它有三个操作:</span></span>
(1)把数列中的一段区间全部乘一个值; 
(2)把数列中的一段区间全部加一个值; 
(3)把数列中的一段区间全部替换成一个值;
然后再对它有一个查询操作:
求数列中的一段区间的每个数的p次方之和(1<=p<=3)

解题思路:
    因为p只有三个值,所以我们可以将这三个值分别进行求解,我将它们定义为sum,sum2,sum3;
结构体定义:
struct Node{
    int l,r;
    ll sum,sum2,sum3;
    int add,mul;
}tree[4*MAXN];
两个lazy-tag标记分别初始化为add=0,mul=1;
我们用两个lazy-tag标记来处理三个更新,对于第三个替换更新,我们可以用前面两个标记进行更新,即mul=0,add=v;然后我们设置lazy-tag标记的优先级,乘法>加法;
细节问题:
<1>(p=1)
(a1*mul+add) + (a1*mul+add) + ... + (an*mul+add) = (a1+a2+...+an)*mul + n*add;
<2>(p=2) 
(a1*mul+add)^2 + (a1*mul+add)^2 + ... + (an*mul+add)^2 = (a1^2+a2^2+...+an^2)*mul^2 + 2*add*mul*(a1+a2+...+an) + n*add^2;
<3>(p=3)
(a1*mul+add)^3 + (a1*mul+add)^3 + ... + (a1*mul+add)^3 = (a1^3+a2^3+...+an^3)*mul^3 +
3*add*mul^2*(a1^2+a2^2+...+an^2) + 3*add^2*mul*(a1+a2+...+an) + n*add^3;

参考代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int MAXN = 100000+5;
typedef long long ll;
#define MOD 10007
struct Node{
	int l,r;
	ll sum,sum2,sum3;
	int add,mul;
}tree[4*MAXN];
void build(int node,int l,int r){
	tree[node].l=l,tree[node].r=r;
	tree[node].add=0,tree[node].mul=1;
	if (l==r){
		tree[node].sum=tree[node].sum2=tree[node].sum3=0;
		return;
	}
	build(node*2,l,(l+r)/2);
	build(node*2+1,(l+r)/2+1,r);
	tree[node].sum=(tree[node*2].sum+tree[node*2+1].sum)%MOD;
	tree[node].sum2=(tree[node*2].sum2+tree[node*2+1].sum2)%MOD;
	tree[node].sum3=(tree[node*2].sum3+tree[node*2+1].sum3)%MOD;
}
void PushDown(int node){
	if (tree[node].add==0 && tree[node].mul==1)
		return;

	tree[node*2].sum3=(tree[node].mul*tree[node].mul%MOD*tree[node].mul%MOD*tree[node*2].sum3%MOD + 3*tree[node].mul*tree[node].mul%MOD*tree[node].add%MOD*tree[node*2].sum2%MOD + 3*tree[node].mul*tree[node].add%MOD*tree[node].add%MOD*tree[node*2].sum%MOD + (tree[node*2].r-tree[node*2].l+1)*tree[node].add%MOD*tree[node].add%MOD*tree[node].add%MOD)%MOD;
	tree[node*2].sum2=(tree[node*2].sum2*tree[node].mul%MOD*tree[node].mul%MOD + 2*tree[node].add*tree[node].mul%MOD*tree[node*2].sum%MOD + (tree[node*2].r-tree[node*2].l+1)*tree[node].add%MOD*tree[node].add%MOD)%MOD;
	tree[node*2].sum=(tree[node*2].sum*tree[node].mul + tree[node].add*(tree[node*2].r-tree[node*2].l+1)%MOD)%MOD;

	tree[node*2+1].sum3=(tree[node].mul*tree[node].mul%MOD*tree[node].mul*tree[node*2+1].sum3%MOD + 3*tree[node].mul*tree[node].mul%MOD*tree[node].add%MOD*tree[node*2+1].sum2%MOD + 3*tree[node].mul*tree[node].add%MOD*tree[node].add%MOD*tree[node*2+1].sum%MOD + (tree[node*2+1].r-tree[node*2+1].l+1)*tree[node].add%MOD*tree[node].add%MOD*tree[node].add%MOD)%MOD;
	tree[node*2+1].sum2=(tree[node*2+1].sum2*tree[node].mul%MOD*tree[node].mul%MOD + 2*tree[node].add*tree[node].mul%MOD*tree[node*2+1].sum%MOD + (tree[node*2+1].r-tree[node*2+1].l+1)*tree[node].add%MOD*tree[node].add%MOD)%MOD;
	tree[node*2+1].sum=(tree[node*2+1].sum*tree[node].mul%MOD + tree[node].add*(tree[node*2+1].r-tree[node*2+1].l+1)%MOD)%MOD;

	tree[node*2].mul=(tree[node*2].mul*tree[node].mul)%MOD;
	tree[node*2].add=(tree[node*2].add*tree[node].mul%MOD+tree[node].add)%MOD;

	tree[node*2+1].mul=(tree[node*2+1].mul*tree[node].mul)%MOD;
	tree[node*2+1].add=(tree[node*2+1].add*tree[node].mul%MOD+tree[node].add)%MOD;

	tree[node].add=0;
	tree[node].mul=1;
}
void Add(int node,int l,int r,int v){
	if (tree[node].l>r || tree[node].r<l)
		return;
	if (l<=tree[node].l && tree[node].r<=r){
		tree[node].sum3=(tree[node].sum3+3*tree[node].sum2%MOD*v%MOD + 3*tree[node].sum%MOD*v%MOD*v%MOD + (tree[node].r-tree[node].l+1)*v%MOD*v%MOD*v%MOD)%MOD;
		tree[node].sum2=(tree[node].sum2+2*tree[node].sum*v%MOD+(tree[node].r-tree[node].l+1)*v%MOD*v%MOD)%MOD;
		tree[node].sum=(tree[node].sum+v*(tree[node].r-tree[node].l+1)%MOD)%MOD;
		tree[node].add=(tree[node].add+v)%MOD;
		return;
	}
	if (tree[node].l==tree[node].r)
		return;
	PushDown(node);
	Add(node*2,l,r,v);
	Add(node*2+1,l,r,v);
	tree[node].sum=(tree[node*2].sum+tree[node*2+1].sum)%MOD;
	tree[node].sum2=(tree[node*2].sum2+tree[node*2+1].sum2)%MOD;
	tree[node].sum3=(tree[node*2].sum3+tree[node*2+1].sum3)%MOD;
}
void Mul(int node,int l,int r,int v){
	if (tree[node].l>r || tree[node].r<l)
		return;
	if (l<=tree[node].l && tree[node].r<=r){
		tree[node].sum3=(tree[node].sum3*v%MOD*v%MOD*v%MOD)%MOD;
		tree[node].sum2=(tree[node].sum2*v%MOD*v)%MOD;
		tree[node].sum=(tree[node].sum*v)%MOD;
		tree[node].add=(tree[node].add*v)%MOD;
		tree[node].mul=(tree[node].mul*v)%MOD;
		return;
	}
	if (tree[node].l==tree[node].r)
		return;
	PushDown(node);
	Mul(node*2,l,r,v);
	Mul(node*2+1,l,r,v);
	tree[node].sum=(tree[node*2].sum+tree[node*2+1].sum)%MOD;
	tree[node].sum2=(tree[node*2].sum2+tree[node*2+1].sum2)%MOD;
	tree[node].sum3=(tree[node*2].sum3+tree[node*2+1].sum3)%MOD;
}
void Change(int node,int l,int r,int v){
	if (tree[node].l>r || tree[node].r<l)
		return;
	if (l<=tree[node].l && tree[node].r<=r){
		tree[node].sum3=((tree[node].r-tree[node].l+1)*v%MOD*v%MOD*v%MOD)%MOD;
		tree[node].sum2=((tree[node].r-tree[node].l+1)*v%MOD*v%MOD)%MOD;
		tree[node].sum=((tree[node].r-tree[node].l+1)*v)%MOD;
		tree[node].add=v%MOD;
		tree[node].mul=0;
		return;
	}
	if (tree[node].l==tree[node].r)
		return;
	PushDown(node);
	Change(node*2,l,r,v);
	Change(node*2+1,l,r,v);
	tree[node].sum=(tree[node*2].sum+tree[node*2+1].sum)%MOD;
	tree[node].sum2=(tree[node*2].sum2+tree[node*2+1].sum2)%MOD;
	tree[node].sum3=(tree[node*2].sum3+tree[node*2+1].sum3)%MOD;
}
ll query(int node,int l,int r,int p){

	if (tree[node].l==l && tree[node].r==r){
		if (p==1)
			return tree[node].sum;
		if (p==2)
			return tree[node].sum2;
		if (p==3)
			return tree[node].sum3;
	}
	PushDown(node);
	int mid=(tree[node].l+tree[node].r)/2;
	if (r<=mid)
		return query(node*2,l,r,p);
	else if (l>mid)
		return query(node*2+1,l,r,p);
	else
		return (query(node*2,l,mid,p)+query(node*2+1,mid+1,r,p))%MOD;
	/*
	if (tree[node].l>r || tree[node].r<l)
		return 0;
	if (l<=tree[node].l && tree[node].r<=r){
		if (p==1)
			return tree[node].sum;
		if (p==2)
			return tree[node].sum2;
		if (p==3)
			return tree[node].sum3;
	}
	if (tree[node].l==tree[node].r)
		return 0;
	PushDown(node);
	return (query(node*2,l,r,p)+query(node*2+1,l,r,p))%MOD;
	*/
}
void Debug(int node){
	/*for (int i=0;i<4*node;i++)
		printf("%lld ",tree[i].sum );
	printf("\n");
	for (int i=0;i<4*node;i++)
		printf("%lld ",tree[i].sum2 );
	printf("\n");
	*/
	for (int i=0;i<200;i++)
		printf("%lld ",tree[i].sum3 );
	printf("\n");
}
int main(){
	int n,m,op,x,y,c,p;
	while (~scanf("%d%d",&n,&m)){
		if (n==0 && m==0) break;
		build(1,1,n);
		while (m--){
			scanf("%d%d%d%d",&op,&x,&y,&c);
			if (op==1)
				Add(1,x,y,c%MOD);
			if (op==2)
				Mul(1,x,y,c%MOD);
			if (op==3)
				Change(1,x,y,c%MOD);
			if (op==4)
				printf("%lld\n",query(1,x,y,c));
			//Debug(n);
		}
	}

	return 0;
}

/*
10000 100
2 56 59 100
1 564 1254 10000
2 7 800 2
3 1 600 9999
4 5 10000 3
2 102 5645 9999
4 568 789 3
4 1 2 1
4 500 1000 1
4 500 1000 2
4 500 1000 3

*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值