hdu 4578 Transformation(线段树区间更新)

本文介绍了一种优化区间操作算法的方法,通过引入特定的数据结构与数学技巧,实现对区间内数值的加、乘、赋值及求幂和操作的高效处理。详细解释了如何使用线性结构存储不同次方的和,并通过简单的数学变换快速更新这些和。通过实例演示,展示了算法的实现过程与应用效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

给你一个数组,初始值为零,有四种操作
(1)”1 x y c”,代表 把区间 [x,y] 上的值全部加c
(2)”2 x y c”,代表 把区间 [x,y] 上的值全部乘以c
(3)”3 x y c” 代表 把区间 [x,y]上的值全部赋值为c
(4)”4 x y p” 代表 求区间 [x,y] 上值的p次方和1<=p<=3

解析:

我们可以把区间内的数字看做 ax+b 的形式。
x 是原来的值,a 当前区间乘上的值,b 是当前区间要加上的值。
因为P只有1到3,所以我们可以开3个数组来保存每个次方的和,分别是sum[1]sum[2]sum[3]

对于加c操作,则变成 ax+b+cb>b+c)。
对于乘c操作,则变成 acx+bca>acb>bc
对于赋值c操作,则变成c,即(a>1x>cb>0

这里要解决的一个问题是加上或乘上一个数对这个区间的p次方和分别产生什么改变,很简单,一化简就能得到。

乘上一个数a之后
sum[1]=asum[1]
sum[2]=a2sum[2]
sum[3]=a3sum[3]

当加上一个数b之后
sum[1]=sum[1]+lenb
sum[2]=sum[2]+2sum[1]b+lenb
sum[3]=sum[3]+3b2sum[1]+3bsum[2]+lenb3
其中len是当前区间的长度。

my code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
const int MOD = (int)1e4 + 7;
const int MAXN = (int)1e5 + 10;
int n, m;

struct Node {
    int L, R;
    int sum[4];
    int mult, addv;

    inline int length() { return R - L + 1; }

    void multiply(int val) {
        mult = (mult * val) % MOD;
        addv = (addv * val) % MOD;
        for(int i = 1; i <= 3; i++) {
            for(int p = 1; p <= i; p++) {
                sum[i] = (sum[i] * val) % MOD;
            }
        }
    }

    void add(int val) {
        int len = length();
        addv = (addv + val) % MOD;

        sum[3] = (sum[3] + 3 * val % MOD * val % MOD * sum[1] % MOD) % MOD;
        sum[3] = (sum[3] + 3 * val % MOD * sum[2] % MOD) % MOD;
        sum[3] = (sum[3] + len * val % MOD * val % MOD * val % MOD) % MOD;

        sum[2] = (sum[2] + 2 * val % MOD * sum[1] % MOD) % MOD;
        sum[2] = (sum[2] + len * val % MOD * val % MOD) % MOD;

        sum[1] = (sum[1] + len * val % MOD) % MOD;
    }

    void cal(int MUL, int ADD) {
        multiply(MUL);
        add(ADD);
    }

} node[MAXN << 2];


void pushDown(int o) {
    if(node[o].mult != 1 || node[o].addv != 0) {
        node[ls].cal(node[o].mult, node[o].addv);
        node[rs].cal(node[o].mult, node[o].addv);
        node[o].mult = 1, node[o].addv = 0;
    }
}

void pushUp(int o) {
    for(int i = 1; i <= 3; i++) {
        node[o].sum[i] = (node[ls].sum[i] + node[rs].sum[i]) % MOD;
    }
}

void build(int o, int L, int R) {
    node[o].L = L, node[o].R = R;
    node[o].addv = 0, node[o].mult = 1;
    memset(node[o].sum, 0, 4*sizeof(int));
    if(L == R) return ;
    int M = (L + R)/2;
    build(lson);
    build(rson);
}

int query(int o, int L, int R, int ql, int qr, int p) {
    if(ql <= L && R <= qr) return node[o].sum[p];
    int M = (L + R)/2, ret = 0;
    pushDown(o);
    if(ql <= M) ret = (ret + query(lson, ql, qr, p)) % MOD;
    if(qr > M) ret = (ret + query(rson, ql, qr, p)) % MOD;
    return ret;
}

void modify(int o, int L, int R, int ql, int qr, int val, int op) {
    if(ql <= L && R <= qr) {
        if(op == 1) node[o].cal(1, val);
        else if(op == 2) node[o].cal(val, 0);
        else node[o].cal(0, val);
        return ;
    }
    int M = (L + R)/2;
    pushDown(o);
    if(ql <= M) modify(lson, ql, qr, val, op);
    if(qr > M) modify(rson, ql, qr, val, op);
    pushUp(o);
}

int main() {
    int op, ql, qr, val;
    while(~scanf("%d%d", &n, &m) && (n || m)) {
        build(1, 1, n);
        while(m--) {
            scanf("%d%d%d%d", &op, &ql, &qr, &val);
            if(op == 4) {
                printf("%d\n", query(1, 1, n, ql, qr, val) % MOD);
            }else {
                modify(1, 1, n, ql, qr, val, op);
            }
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值