HDU - 4578 Transformation

HDU - 4578 Transformation
题 意:给你n个数字,开始都是0,m次操作,1 x y p:区间[x,y]每个数都加上p。2 x y c
:区间[x,y]全部都乘p,3 x y c.将区间[x,y]的值全部都设为c。4 x y p,查询[x,y]所有值的p次方和。
数据范围:

1<=n,m<=1e5
1<=c<=1e4
x,y<=n
1<=p<=3
输入样例:

5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0

输出样例:

307
7489

思 路:用三个懒惰标记add,mul,set。注意懒惰标记pushdown的次序。
收 获:学会了set,mul,add的懒惰标记的打法。以及混和的打法

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
const int mod = 10007;
ll add[maxn<<2],mul[maxn<<2],se[maxn<<2];
ll sum1[maxn<<2],sum2[maxn<<2],sum3[maxn<<2];
int n,m;
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 l,int r,int rt){
    add[rt] = se[rt] = 0;
    mul[rt] = 1;
    if(l == r){
        sum1[rt] = sum2[rt] = sum3[rt] = 0;
        return;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void PushDown(int rt,int len){
    if(se[rt]){
        add[rt<<1|1] = add[rt<<1] = 0;
        mul[rt<<1|1] = mul[rt<<1] = 1;
        se[rt<<1] = se[rt<<1|1] = se[rt];
        sum3[rt<<1] = ((((((len-(len>>1))*se[rt]%mod)%mod)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
        sum3[rt<<1|1] = ((((((len>>1)*se[rt]%mod)%mod)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
        sum2[rt<<1] = ((((len-(len>>1))*se[rt]%mod)%mod)*se[rt]%mod)%mod;
        sum2[rt<<1|1] = ((((len>>1)*se[rt]%mod)%mod)*se[rt]%mod)%mod;
        sum1[rt<<1] = ((len-(len>>1))*se[rt]%mod)%mod;
        sum1[rt<<1|1] = ((len>>1)*se[rt]%mod)%mod;
        se[rt] = 0;
    }
    if(mul[rt]!=1){
        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;
        }
        mul[rt<<1] =(mul[rt]*mul[rt<<1])%mod;
        mul[rt<<1|1] =(mul[rt<<1|1] * mul[rt])%mod;

        sum3[rt<<1] = (((((((sum3[rt<<1])%mod)*mul[rt])%mod)*mul[rt])%mod)*mul[rt])%mod;
        sum3[rt<<1|1] = (((((sum3[rt<<1|1]*mul[rt]%mod)%mod)*mul[rt])%mod)*mul[rt])%mod;
        sum2[rt<<1] = (((sum2[rt<<1]*mul[rt]%mod)%mod)*mul[rt])%mod;
        sum2[rt<<1|1] = (((sum2[rt<<1|1]*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;
        mul[rt] = 1;
    }
    if(add[rt]){
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];
        int tmp = (((((add[rt])%mod)*add[rt])%mod)*add[rt])%mod;
        sum3[rt<<1] = ((sum3[rt<<1]+ (tmp*(len-(len>>1)))%mod + ((3*add[rt])%mod)*(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])%mod)*(sum2[rt<<1|1]+sum1[rt<<1|1]*add[rt])%mod)%mod;
        sum2[rt<<1] = (sum2[rt<<1] + (((len-(len>>1))*add[rt]%mod)*add[rt]%mod) + (2*add[rt]*sum1[rt<<1])%mod)%mod;
        sum2[rt<<1|1] = (sum2[rt<<1|1] + ((((len>>1))*add[rt]%mod)*add[rt]%mod) + (2*add[rt]*sum1[rt<<1|1])%mod)%mod;
        sum1[rt<<1] = (sum1[rt<<1] + ((len - (len>>1))*add[rt])%mod)%mod;
        sum1[rt<<1|1] = (sum1[rt<<1|1] + ((len>>1)*add[rt])%mod)%mod;
        add[rt] = 0;
    }
}
void update(int L,int R,int x,int p,int l,int r,int rt){
    if(L<=l && r<=R){
        if(p == 3){
             se[rt] = x;
             mul[rt] = 1;
             add[rt] = 0;
             sum3[rt] = ((((((r-l+1)*x)%mod)*x)%mod)*x)%mod;
             sum2[rt] = (((r-l+1)*x%mod)*x%mod)%mod;
             sum1[rt] = ((r-l+1)*x)%mod;
        }else if(p==2){
            mul[rt]=(x*mul[rt])%mod;
            if(add[rt]){
                add[rt] = (add[rt]*x)%mod; 
            }
            sum3[rt] = ((((((sum3[rt]%mod)*x)%mod)*x)%mod)*x)%mod;
            sum2[rt] = (((sum2[rt]*x)%mod)*x)%mod;
            sum1[rt] = (sum1[rt]*x)%mod;
        }else if(p == 1){
            add[rt]+=x;
            sum3[rt] = (sum3[rt] + ((((((r-l+1)*x)%mod)*x)%mod)*x)%mod +((3*x)%mod)*(sum2[rt] + (sum1[rt]*x)%mod))%mod;
            sum2[rt] = (sum2[rt]+((((r-l+1)*x)%mod)*x)%mod + 2*x*sum1[rt]%mod)%mod;
            sum1[rt] = (sum1[rt] + ((r-l+1)*x)%mod)%mod;
        }
        return ;
    }
    PushDown(rt,r-l+1);
    int m = (l+r)/2;
    if(L<=m) update(L,R,x,p,lson);
    if(R>m) update(L,R,x,p,rson);
    PushUp(rt);
}
ll query(int L,int R,int p,int l,int r,int rt){
    if(L <= l && r<=R){
        if(p==1){
            return sum1[rt]%mod;
        }else if(p == 2){
            return sum2[rt]%mod;
        }else{
            return sum3[rt]%mod;
        }
    }
    PushDown(rt,r-l+1);
    int m = (l+r)>>1,ans = 0;
    if(L<=m) ans=(ans+query(L,R,p,lson))%mod;
    if(R>m) ans=(ans+query(L,R,p,rson))%mod;
    return ans;
}
int main(){
    while(~scanf("%d %d",&n,&m) && (n+m)){
        build(1,n,1);
        int a,l,r,p;
        for(int i=0;i<m;i++){
            scanf("%d %d %d %d",&a,&l,&r,&p);
            if(a != 4){
                update(l,r,p,a,1,n,1);
            }else{
                ll ans = query(l,r,p,1,n,1);
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
/*
2
6 2 4
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值