Realization of multiple operations on HDU4578 line segment tree

Just post the code:
This question has a large amount of code. The
most important thing is to learn how to deal with the sequence relationship between multiple operations and different marks,
and the algebraic relationship between the sum value before and after the summation must be written. Come out for easy understanding

#include <bits/stdc++.h>
// 精品好题
using namespace std;
typedef long long ll;
const int MAXN = 1e5+7;
const int MOD = 10007;
ll add[MAXN<<2],se[MAXN<<2],mul[MAXN<<2];//add是加 set重置 mul乘 三种懒惰标记
ll sum1[MAXN<<2],sum2[MAXN<<2],sum3[MAXN<<2];//直接求和 平方和 立方和
// 多种操作时 要注意重置操作 优先级最高 重置之后 加等于0 乘等于1
// 在进行乘法操作时 如果当前有加法标记 那么加法标记也要相应的先乘以这个标记进行更新
// 而对于加法操作 因为涉及到平方和立方的操作 具体要推倒 新的节点与之前节点的值具有怎样的关系 关系找出来才能解决问题

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 rt,int l,int r)
{
    
    
	add[rt] = se[rt] = 0;//都相当于一开始初始化操作
	mul[rt] = 1;
	if(l == r){
    
    
		sum1[rt] = sum2[rt] = sum3[rt] = 0;
		return ;
	}
	int mid = (l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}

void pushdown(int rt,int len)
{
    
    
	if(se[rt]){
    
    
		se[rt<<1] = se[rt<<1|1] = se[rt];
		add[rt<<1] = add[rt<<1|1] = 0;// 当碰到重置的时候 先将加的变为0 乘的要变为1
		mul[rt<<1] = mul[rt<<1|1] = 1;
		ll tmp = ((se[rt] * se[rt]) % MOD) * se[rt] % MOD;
        sum1[rt << 1] = ((len - (len >> 1)) % MOD) * (se[rt] % MOD) % MOD;
        sum1[rt << 1 | 1] = ((len >> 1) % MOD) * (se[rt] % MOD) % MOD;
        sum2[rt << 1] = ((len - (len >> 1)) % MOD) * ((se[rt] * se[rt]) % MOD) % MOD;
        sum2[rt << 1 | 1] = ((len >> 1) % MOD) * ((se[rt] * se[rt]) % MOD) % MOD;
        sum3[rt << 1] = ((len - (len >> 1)) % MOD) * tmp % MOD;
        sum3[rt << 1 | 1] = ((len >> 1) % MOD) * tmp % MOD;
        se[rt] = 0;	
    }
	if(mul[rt] != 1) {
    
        //这个就是mul[rt] != 1 , 当时我这里没注意所以TLE了
        mul[rt << 1] = (mul[rt << 1] * mul[rt]) % MOD;
        mul[rt << 1 | 1] = (mul[rt << 1 | 1] * mul[rt]) % MOD;
        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;
        ll tmp = (((mul[rt] * 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;
        sum2[rt << 1] = (sum2[rt << 1] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
        sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
        sum3[rt << 1] = (sum3[rt << 1] % MOD) * tmp % MOD;
        sum3[rt << 1 | 1] = (sum3[rt << 1 | 1] % MOD) * tmp % MOD;
        mul[rt] = 1;
    }
	if(add[rt]) {
    
    
        add[rt << 1] += add[rt];    //add是+= , mul是*=
        add[rt << 1 | 1] += add[rt];
        ll tmp = (add[rt] * add[rt] % MOD) * add[rt] % MOD;        //注意sum3 , sum2 , sum1的先后顺序
        sum3[rt << 1] = (sum3[rt << 1] + (tmp * (len - (len >> 1)) % MOD) + 3 * add[rt] * ((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] * ((sum2[rt << 1 | 1] + sum1[rt << 1 | 1] * add[rt]) % MOD)) % MOD;
        sum2[rt << 1] = (sum2[rt << 1] + ((add[rt] * add[rt] % MOD) * (len - (len >> 1)) % MOD) + (2 * sum1[rt << 1] * add[rt] % MOD)) % MOD;
        sum2[rt << 1 | 1] = (sum2[rt << 1 | 1] + (((add[rt] * add[rt] % MOD) * (len >> 1)) % MOD) + (2 * sum1[rt << 1 | 1] * add[rt] % MOD)) % MOD;
        sum1[rt << 1] = (sum1[rt << 1] + (len - (len >> 1)) * add[rt]) % MOD;
        sum1[rt << 1 | 1] = (sum1[rt << 1 | 1] + (len >> 1) * add[rt]) % MOD;
        add[rt] = 0;
    }
}

void update(int rt,int l,int r,int ul,int ur,int k,int c)
{
    
    
	 if(ul <= l && ur >= r) {
    
    
        if(k == 3) {
    
    
            se[rt] = c;
            add[rt] = 0;
            mul[rt] = 1;
            sum1[rt] = ((r - l + 1) * c) % MOD;
            sum2[rt] = ((r - l + 1) * ((c * c) % MOD)) % MOD;
            sum3[rt] = ((r - l + 1) * (((c * c) % MOD) * c % MOD)) % MOD;
        } else if(k == 2) {
    
    
            mul[rt] = (mul[rt] * c) % MOD;
            if(add[rt])
                add[rt] = (add[rt] * c) % MOD;
            sum1[rt] = (sum1[rt] * c) % MOD;
            sum2[rt] = (sum2[rt] * (c * c % MOD)) % MOD;
            sum3[rt] = (sum3[rt] * ((c * c % MOD) * c % MOD)) % MOD;
        } else if(k == 1) {
    
    
            add[rt] += c;
            ll tmp = (((c * c) % MOD * c) % MOD * (r - l + 1)) % MOD;    //(r - l + 1) * c^3
            sum3[rt] = (sum3[rt] + tmp + 3 * c * ((sum2[rt] + sum1[rt] * c) % MOD)) % MOD;
            sum2[rt] = (sum2[rt] + (c * c % MOD * (r - l + 1) % MOD) + 2 * sum1[rt] * c) % MOD;
            sum1[rt] = (sum1[rt] + (r - l + 1) * c) % MOD;
        }
        return ;
    }
	pushdown(rt,r-l+1);
	int mid = (l+r)>>1;
	if(ul <= mid) update(rt<<1,l,mid,ul,ur,k,c);
	if(ur > mid) update(rt<<1|1,mid+1,r,ul,ur,k,c);
	pushup(rt);
}

ll query(int rt,int l,int r,int ql,int qr,int q)
{
    
    
	if(l>=ql&&r<=qr){
    
    
		if(q==1)
			return sum1[rt];
		else if(q==2)
			return sum2[rt];
		else
			return sum3[rt];
	}
	pushdown(rt,r-l+1);
	int mid = (l+r)>>1;
	ll ans = 0;
	if(ql <= mid) ans += query(rt<<1,l,mid,ql,qr,q);
	if(qr > mid) ans += query(rt<<1|1,mid+1,r,ql,qr,q); 
	return ans%MOD;
}

int main()
{
    
    
	int n,m;
	while(~scanf("%d%d",&n,&m)&&(n&&m)){
    
    
		build(1,1,n);
		int a,x,y,val;
		while(m--){
    
    
			scanf("%d%d%d%d",&a,&x,&y,&val);
			if(a != 4){
    
    
				update(1,1,n,x,y,a,val);
			}
			else{
    
    
				printf("%lld\n",query(1,1,n,x,y,val));
			}
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45672411/article/details/107221919