hdu 4578 Transformation

本文详细介绍了一种高效的数据结构——线段树,并提供了一个具体的实现案例。通过该案例,读者可以了解到如何利用线段树解决区间更新和查询的问题。

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

http://acm.hdu.edu.cn/showproblem.php?pid=4578

算是裸的线段树,不难推出来把所有过程看成 x * a + b ,a、b的值随情况而定。。。把3种下推更新放在同一个公式更新里

#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <set>
#include <iostream>
#include <cmath>
using namespace std;
#ifdef __GNUC__
#define LL long long
#else
#define LL __int64
#endif

/*
    add = x * 1 + b;
    set = x * 0 + b;
    multiply = x * c + 0;
*/

const int MAXN = 100005;
const LL MOD = 10007;
LL mult[MAXN*3];        // multiply sign;
LL add_set[MAXN*3];    // add and set number;
LL sum1[MAXN*3], sum2[MAXN*3], sum3[MAXN*3];

#define lson l,m,(cnt<<1)
#define rson m+1,r,((cnt<<1)+1)
#define mid m=(l+r)>>1
int m, n;
void build(int l, int r, int cnt)
{
    add_set[cnt] = 0;
    mult[cnt] = 1; 
    sum1[cnt] = sum2[cnt] = sum3[cnt] = 0;
    if (l == r) return;
    int mid;
    build(lson);
    build(rson);
}

 void calcu(int cnt, int mt, int da, int num)
{
    LL d[3], c[3];
    d[0] = mt; d[1] = mt*mt%MOD; d[2] = d[1]*mt%MOD;
    c[0] = da; c[1] = da*da%MOD; c[2] = c[1]*da%MOD;
    sum3[cnt] = (d[2]*sum3[cnt] + num*c[2] + 3*d[1]*c[0]*sum2[cnt] + 3*d[0]*c[1]*sum1[cnt])%MOD;
    sum2[cnt] = (d[1]*sum2[cnt] + num*c[1] + 2*d[0]*c[0]*sum1[cnt])%MOD;
    sum1[cnt] = (d[0]*sum1[cnt] + num*c[0])%MOD;
}

void pushDown ( int l, int r, int cnt )
{
    if (mult[cnt] == 1 && add_set[cnt] == 0) return;
    int mid;
    int ll = cnt<<1;
    int rr = ll | 1;
    mult[ll] = (mult[cnt]*mult[ll])%MOD;
    add_set[ll] = (add_set[ll]*mult[cnt]+add_set[cnt])%MOD;
    calcu(ll, mult[cnt], add_set[cnt], m-l+1);
    mult[rr] = (mult[cnt]*mult[rr])%MOD;
    add_set[rr] = (add_set[rr]*mult[cnt]+add_set[cnt])%MOD;
    calcu(rr, mult[cnt], add_set[cnt], r-m);
    mult[cnt] = 1;
    add_set[cnt] = 0;
    
}

void pushUp(int l, int r, int cnt)
{
    int ll = cnt<<1;
    int rr = ll | 1;
    sum1[cnt] = (sum1[ll]+sum1[rr])%MOD;
    sum2[cnt] = (sum2[ll]+sum2[rr])%MOD;
    sum3[cnt] = (sum3[ll]+sum3[rr])%MOD;
}

void madd(int da, int mt, int x, int y, int l, int r, int cnt)
{
    if ( x <= l && y >= r)
    {
        mult[cnt] = (mult[cnt]*mt)%MOD;
        add_set[cnt] = (add_set[cnt]*mt + da)%MOD;
        calcu(cnt, mt, da, r-l+1);
        return ;
    }
	pushDown(l, r, cnt);
    int mid;
    if (x <= m) madd(da, mt, x, y, lson);
    if (y > m) madd(da, mt, x, y, rson);
    pushUp(l, r, cnt);
}

LL mquery(int x, int y, int cc, int l, int r, int cnt)
{
    LL res = 0;
    if (x <= l && y >= r)
    {
        switch(cc)
        {
        case 1: return sum1[cnt];
        case 2: return sum2[cnt];
        case 3: return sum3[cnt];
        }
    }
	pushDown(l, r, cnt);
    int mid;
    if (x <= m) res += mquery(x, y, cc, lson);
    if (y > m) res += mquery(x, y, cc, rson);
    return res;
}

int main() 
{
#ifdef __GNUC__
    freopen("in.txt", "r", stdin);
#endif
    while (scanf("%d%d", &n, &m) != EOF && n+m)
    {
        build(1, n, 1);
        while (m--)
        {
            int a, x, y, c;
            scanf("%d%d%d%d", &a, &x, &y, &c);
            if (a == 1)
            {
                madd(c, 1, x, y, 1, n, 1);
            }
            else if (a == 2)
            {
                madd(0, c, x, y, 1, n, 1);
            }
            else if (a == 3)
            {
                madd(c, 0, x, y, 1, n, 1);
            }
            else
            {
                LL res = mquery(x, y, c, 1, n, 1);
                res %= MOD;
                printf("%I64d\n", res);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值