HDU - 4578 Transformation (线段树 有点复杂)

这个博客讲的很详细了。

但是有一个地方是错误的

https://blog.csdn.net/HelloWorld10086/article/details/48084941

这个地方要在乘 一个 b。

代码:

#include<bits/stdc++.h>
#define ls now << 1
#define rs now << 1 | 1
using namespace std;
const int N = 1e5+100;
const int mod = 10007;
int n,m,op;
long long lza[N*4],lzm[N*4],lzc[N*4];
long long sum[N*4][3];
long long ans[3];
void op3(int now,int len, int k){
    lzc[now] = k; lza[now] = 0; lzm[now] = 1;
    sum[now][0] = (1ll*len*k) % mod;
    sum[now][1] = ((1ll*len*k) % mod *k) % mod;
    sum[now][2] = (((1ll*len*k)%mod*k)%mod*k)%mod;    
}

void op2(int now, int k){
    lzm[now] = lzm[now]*k%mod; lza[now] = lza[now] * k % mod;
    sum[now][0] = (sum[now][0]*k)%mod;
    sum[now][1] = ((sum[now][1]*k)%mod*k)%mod;
    sum[now][2] = (((sum[now][2]*k)%mod*k)%mod*k)%mod;    
}
void op1(int now, int len, int k){
    lza[now] += k;
    sum[now][2] += ((1ll*3*sum[now][0]*k)%mod*k)%mod + (1ll*3*k*sum[now][1])%mod+(((1ll*len*k)%mod*k)%mod*k)%mod;     
    sum[now][1] += (1ll*2*sum[now][0]*k)%mod + ((1ll*len*k)%mod*k)%mod;
    sum[now][0] += (1ll*len*k)%mod;
    sum[now][0] %= mod; sum[now][1] %= mod; sum[now][2] %= mod;
}

void pushdown(int now, int l, int r){
    int mid = (l + r) >> 1;
    if (lzc[now]){
        op3(ls,mid-l,lzc[now]); op3(rs,r-mid,lzc[now]);
        lzc[now] = 0;
    } 
    if (lzm[now] == 1 && lza[now] == 0) return;
    op2(ls,lzm[now]); op2(rs,lzm[now]);
    op1(ls,mid-l,lza[now]); op1(rs,r-mid,lza[now]);
    lza[now] = 0; lzm[now] = 1;
    
}
void pushup(int now, int l, int r){
    sum[now][0] = (sum[l][0] + sum[r][0])%mod;
    sum[now][1] = (sum[l][1] + sum[r][1])%mod;
    sum[now][2] = (sum[l][2] + sum[r][2])%mod;
}
void build(int now, int l, int r){
    sum[now][0] = sum[now][1] = sum[now][2] = 0;
    lza[now] = 0; lzm[now] = 1; lzc[now] = 0;    
    if (l + 1 == r) return;
    int mid = (l + r) >> 1;
    build(ls,l,mid); build(rs,mid,r);
}
void modify(int now, int l, int r, int a, int b, int k){
    if (a <= l && b >= r-1){
        int len = r - l;
        if (op == 1){
            op1(now,len,k);
        } else if (op == 2) {
            op2(now,k);
        } else{
            op3(now,len,k);
        }
        return;
    }
    pushdown(now,l,r);
    int mid = (l + r) >> 1;
    if (a < mid) modify(ls,l,mid,a,b,k);
    if (b >= mid) modify(rs,mid,r,a,b,k);
    pushup(now,ls,rs);
}
void query(int now, int l, int r, int a, int b){
    if (a <= l && b >= r-1){
        ans[0] += sum[now][0]; ans[1] += sum[now][1]; ans[2] += sum[now][2];
        ans[0] %= mod; ans[1] %= mod; ans[2] %= mod;
        return;
    }
    pushdown(now,l,r);
    int mid = (l + r) >>1;
    if (a < mid) query(ls,l,mid,a,b);
    if (b >= mid) query(rs,mid,r,a,b);
}
int main(){
    int x,y,z;
    while(~scanf("%d%d",&n,&m)){
        if (n == 0) break;
        build(1,1,n+1);
        for (int i = 0; i < m; ++i){
            scanf("%d%d%d%d",&op,&x,&y,&z);
            if (op == 4){
                ans[0] = ans[2] = ans[1] = 0;
                query(1,1,n+1,x,y);
                printf("%lld\n",ans[z-1]);
            }else{
                modify(1,1,n+1,x,y,z);
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值