hdu 4578 Transformation (线段树 + 延迟标记)

题目链接:hdu 4578

思路:这道题目有个关键点,就是三个操作的优先级,优先级如下:1改变>2乘>3加,可以这么理解,先定义三个lazy0,lazy1,lazy2的意义,分别表示将要加的数,将要乘上的数,将要变成的数c,那么一旦你执行操作1(改变),那么lazy2=c, lazy1要置为1,lazy0要置于0,同样,你一旦操作2乘c,那么你lazy1=lazy1*c,lazy0=lazy0*c。 最后,你如果操作3加,那么你只要将lazy0=lazy0 + c. 所以可以看出优先级是改变>乘>加。 因此pushdown的时候,因先对优先级高的先操作,因为它会影响后面的操作。

代码:

#include<cstdio>
#define ll long long 
const int mod = 10007;
const int maxn = 1e5+5;
#define mid (L + R)/2
#define ls rt*2
#define rs rt*2+1
#define lson ls,L,mid
#define rson rs,mid+1,R
ll sum[maxn<<2], sum1[maxn<<2], sum2[maxn<<2];
ll lazy0[maxn<<2], lazy1[maxn<<2], lazy2[maxn<<2];//加,乘,变 
void build(int rt, int L, int R)
{
	lazy0[rt]=lazy2[rt]=sum[rt]=sum1[rt]=sum2[rt]= 0;
	lazy1[rt] = 1;
	if(L == R) return ;
	build(lson);
	build(rson);
}
void pushDown(int rt, int  L, int R)
{
	if(lazy2[rt]){//变 
		sum2[ls] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(mid-L+1))%mod;
		sum2[rs] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(R-mid))%mod;
		sum1[ls] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(mid-L+1))%mod;
		sum1[rs] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(R-mid))%mod;
		sum[ls] = 1ll*lazy2[rt]*(mid-L+1)%mod; 
		sum[rs] = 1ll*lazy2[rt]*(R-mid)%mod;
		lazy2[ls] = lazy2[rs] = lazy2[rt];
		lazy1[ls] = lazy1[rs] = 1;
		lazy0[ls] = lazy0[rs] = 0;
		lazy2[rt] = 0;
	}
	if(lazy1[rt] != 1){//乘 
		sum2[ls] = 1ll*((sum2[ls]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
		sum2[rs] = 1ll*((sum2[rs]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
		sum1[ls] = 1ll*(sum1[ls]*lazy1[rt])%mod*lazy1[rt]%mod;
		sum1[rs] = 1ll*(sum1[rs]*lazy1[rt])%mod*lazy1[rt]%mod;
		sum[ls] = 1ll*sum[ls]*lazy1[rt]%mod;
		sum[rs] = 1ll*sum[rs]*lazy1[rt]%mod;
		lazy1[ls] = 1ll*lazy1[ls]*lazy1[rt]%mod;
		lazy1[rs] = 1ll*lazy1[rs]*lazy1[rt]%mod;
		if(lazy0[ls])
			lazy0[ls] = 1ll*lazy0[ls]*lazy1[rt]%mod;
		if(lazy0[rs])
			lazy0[rs] = 1ll*lazy0[rs]*lazy1[rt]%mod;
		lazy1[rt] = 1;
	}
	if(lazy0[rt]){//加 sum2[rt] + 1ll*(R-L+1)*val*val*val + 3ll*val*(sum[rt]*val + 1ll*sum1[rt]);
		sum2[ls] = sum2[ls] + 1ll*((mid-L+1)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*(lazy0[rt]*((sum[ls]*lazy0[rt])%mod + 1ll*sum1[ls])%mod)%mod;
		sum2[ls] %= mod;
		sum2[rs] = sum2[rs] + 1ll*((R-mid)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*lazy0[rt]*(sum[rs]*lazy0[rt] + 1ll*sum1[rs]);
		sum2[rs] %= mod;
		sum1[ls] = sum1[ls] + 1ll*lazy0[rt]*lazy0[rt]*(mid-L+1) + 2ll*sum[ls]*lazy0[rt];
		sum1[ls] %= mod;
		sum1[rs] = sum1[rs] + 1ll*lazy0[rt]*lazy0[rt]*(R-mid) + 2ll*sum[rs]*lazy0[rt];
		sum1[rs] %= mod;
		sum[ls] = sum[ls] + 1ll*lazy0[rt]*(mid-L+1);
		sum[ls] %= mod;
		sum[rs] = sum[rs] + 1ll*lazy0[rt]*(R-mid);
		sum[rt] %= mod;
		lazy0[ls] += lazy0[rt];
		lazy0[ls] %= mod;
		lazy0[rs] += lazy0[rt];
		lazy0[rs] %= mod; 
		lazy0[rt] = 0;
	}
}
void upDate(int rt, int L, int R, int l, int r, ll val, int op)
{
	if(l <= L && R <= r){//加 
		if(op == 1){
			sum2[rt] = sum2[rt] + 1ll*(R-L+1)*((val*val)%mod*val)%mod + 3ll*val*(((sum[rt]*val)%mod + 1ll*sum1[rt]))%mod;
			sum2[rt] %= mod;
			sum1[rt] = sum1[rt]+1ll*(R-L+1)*(val*val)%mod+2ll*(val*sum[rt])%mod;
			sum1[rt] %= mod;
			sum[rt] = sum[rt] + 1ll*val*(R - L + 1);
			sum[rt] %= mod;			
			lazy0[rt] += val;
			lazy0[rt] %= mod;
		}
		else if(op == 2){//乘 
			sum2[rt] = 1ll*sum2[rt]*((val*val)%mod*val)%mod;
			sum1[rt] = 1ll*(sum1[rt] * (val*val)%mod)%mod;
			sum[rt] = 1ll*val*sum[rt]%mod;
			if(lazy0[rt])
				lazy0[rt] = 1ll*lazy0[rt]*val%mod;
			lazy1[rt] = 1ll*lazy1[rt]*val%mod;
		}
		else if(op == 3){//变 
			sum2[rt] = 1ll*((val*val)%mod*val*(R-L+1))%mod;
			sum1[rt] = 1ll*val*val*(R-L+1)%mod;
			sum[rt] = 1ll*val*(R - L + 1)%mod;
			lazy0[rt] = 0;
			lazy1[rt] = 1;
			lazy2[rt] = val;
		}
		return ;
	}
	pushDown(rt, L, R);
	if(l <= mid) upDate(lson, l, r, val, op);
	if(r > mid) upDate(rson, l, r, val, op);
	sum[rt] = sum[ls] + sum[rs];
	sum1[rt] = sum1[ls] + sum1[rs];
	sum2[rt] = sum2[ls] + sum2[rs];
	sum[rt] %= mod;
	sum1[rt] %= mod;
	sum2[rt] %= mod;
}
ll query(int rt, int L, int R, int l, int r, int op)
{
	if(l <= L && R <= r){
		if(op == 1){
			return sum[rt];
		}
		else if(op == 2){
			return sum1[rt];
		}
		else if(op == 3){
			return sum2[rt];
		}
	}
	ll res = 0ll;
	pushDown(rt,L,R);
	if(l <= mid) res += query(lson,l,r,op);
	if(r > mid) res += query(rson,l,r,op);
	return res%mod;
}
int main()
{
	ll n, m;
	ll a, b, c, d;
	while(~scanf("%lld%lld", &n, &m)){
		if(n==0 && m== 0)break;
		build(1, 1, n);
		for(int i = 0; i < m; i++){
			scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
			if(a == 1){
				upDate(1,1,n,b,c,d,1);
			}
			else if(a == 2){
				upDate(1,1,n,b,c,d,2);
			}
			else if(a == 3){
				upDate(1,1,n,b,c,d,3);
			}
			else if(a == 4){
				ll ans = query(1,1,n,b,c,d);
				printf("%lld\n", ans);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35930475/article/details/80418186
今日推荐