hdu 4578 线段树 成段+ 成段* 成段替换 区间求平方和 立方和

来源:互联网 发布:淘宝靠谱法国代购推荐 编辑:程序博客网 时间:2024/04/27 21:20

题意:

RT- -

四种操作:

1 x y c :  ak<---ak+c, k = x,x+1,…,y

2 x y c : ak<---ak×c, k = x,x+1,…,y

3 x y c : ak<---c, k = x,x+1,…,y

4 x y p : axp+ax+1p+…+ayp


解析:

http://blog.csdn.net/shiqi_614/article/details/9939485

重新理解了懒惰标记的用法。

总觉得线段树学了和没学差不多T T 只会模板。

这题,把和,平方和,立方和,拆成了三个sum,然后操作懒惰标记的时候有特殊的技巧,处理sum的时候也有特殊技巧。


处理操作1的时候:

void runAdd(int rt, LL val){    add[rt] = (add[rt] + val) % mod;    LL sum1 = sum[rt][1];    LL sum2 = sum[rt][2];    LL sum3 = sum[rt][3];    sum[rt][1] += (val * sz[rt]) % mod;    sum[rt][1] %= mod;    sum[rt][2] += (2 * val * sum1) % mod + (val * val * sz[rt]) % mod;    sum[rt][2] %= mod;    sum[rt][3] += (3 * val * sum2) % mod + (3 * val * val * sum1) % mod + (val * val * val * sz[rt]) % mod;    sum[rt][3] %= mod;}

延迟的加标记,直接加上去就好了。

sum[ rt ][ 1 ]表示和,和处理+只要整段的加上这个区间就ok了;

sum[ rt ][ 2 ]表示平方和,这个处理的时候举个例子直接算就行了:

(a ^ 2 + b ^ 2)   ===>  ( a + val ) ^ 2 + (b + val ) ^ 2

这个过程中,把右边展开,然后发现左边只要加上 (2 * val * sum1)  + (val * val * sz[rt]),就达到了更新和的目的。

sum[ rt ][ 3 ]表示立方和,这个处理如上一样也举个例子就理解了:

(a ^ 3 + b ^ 3)    ===> ( a + val ) ^ 3 + ( b + val ) ^ 3

如上,右边展开加上(3 * val * sum2)  + (3 * val * val * sum1) + (val * val * val * sz[rt]) ,也达到了更新和的目的。


处理操作2的时候:

void runMult(int rt, LL val){    if (mult[rt])        mult[rt] = (mult[rt] * val) % mod;    else        mult[rt] = val;    add[rt] = (add[rt] * val) % mod;    LL sum1 = sum[rt][1];    LL sum2 = sum[rt][2];    LL sum3 = sum[rt][3];    sum[rt][1] = (sum1 * val) % mod;    sum[rt][2] = (sum2 * val * val) % mod;    sum[rt][3] = (sum3 * val * val * val) % mod;}
乘法的延迟操作需要加一个判断,并且对未加掉的加法懒惰标记有*val的影响。

然后成多少的和,平方和,立方和,这个很好推。


处理操作3:

void runSame(int rt, LL val){    same[rt] = val;    add[rt] = mult[rt] = 0;    sum[rt][1] = (val * sz[rt]) % mod;    sum[rt][2] = (val * val * sz[rt]) % mod;    sum[rt][3] = (val * val * val * sz[rt]) % mod;}
操作3相对较简单,因为直接覆盖上去了,所以加法乘法的懒惰标记直接归成0。

然后改成啥,区间和就累加成啥。


在向下更新的时候,先判断覆盖的操作,随后加与乘的顺序无所谓。

void pushdown(int rt){    if (same[rt])    {        runSame(rt << 1, same[rt]);        runSame(rt << 1 | 1, same[rt]);        same[rt] = 0;    }    if (mult[rt])    {        runMult(rt << 1, mult[rt]);        runMult(rt << 1 | 1, mult[rt]);        mult[rt] = 0;    }    if (add[rt])    {        runAdd(rt << 1, add[rt]);        runAdd(rt << 1 | 1, add[rt]);        add[rt] = 0;    }}


完整代码:

#pragma comment(linker, "/STACK:1677721600")#include <map>#include <set>#include <cmath>#include <queue>#include <stack>#include <vector>#include <cstdio>#include <cstdlib>#include <cstring>#include <climits>#include <cassert>#include <iostream>#include <algorithm>#define pb push_back#define mp make_pair#define LL long long#define lson lo,mi,rt<<1#define rson mi+1,hi,rt<<1|1#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define mem(a,b) memset(a,b,sizeof(a))#define FIN freopen("in.txt", "r", stdin)#define FOUT freopen("out.txt", "w", stdout)#define rep(i,a,b) for(int i=(a); i<=(b); i++)#define dec(i,a,b) for(int i=(a); i>=(b); i--)using namespace std;const int mod = 10007;const double eps = 1e-8;const double ee = exp(1.0);const int inf = 0x3f3f3f3f;const int maxn = 1e5 + 10;const double pi = acos(-1.0);const LL iinf = 0x3f3f3f3f3f3f3f3f;int readT(){    char c;    int ret = 0,flg = 0;    while(c = getchar(), (c < '0' || c > '9') && c != '-');    if(c == '-') flg = 1;    else ret = c ^ 48;    while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);    return flg ? - ret : ret;}struct Segtree{    LL add[maxn << 2], mult[maxn << 2], same[maxn << 2], sz[maxn << 2];    LL sum[maxn << 2][4];    void pushup(int rt)    {        sum[rt][1] = (sum[rt << 1][1] + sum[rt << 1 | 1][1]) % mod;        sum[rt][2] = (sum[rt << 1][2] + sum[rt << 1 | 1][2]) % mod;        sum[rt][3] = (sum[rt << 1][3] + sum[rt << 1 | 1][3]) % mod;    }    void build(int lo, int hi, int rt)    {        add[rt] = mult[rt] = same[rt] = 0;        sum[rt][1] = sum[rt][2] = sum[rt][3] = 0;        sz[rt] = hi - lo + 1;        if (lo == hi)        {            return;        }        int mi = (lo + hi) >> 1;        build(lson);        build(rson);        pushup(rt);    }    void runAdd(int rt, LL val)    {        add[rt] = (add[rt] + val) % mod;        LL sum1 = sum[rt][1];        LL sum2 = sum[rt][2];        LL sum3 = sum[rt][3];        sum[rt][1] += (val * sz[rt]) % mod;        sum[rt][1] %= mod;        sum[rt][2] += (2 * val * sum1) % mod + (val * val * sz[rt]) % mod;        sum[rt][2] %= mod;        sum[rt][3] += (3 * val * sum2) % mod + (3 * val * val * sum1) % mod + (val * val * val * sz[rt]) % mod;        sum[rt][3] %= mod;    }    void runMult(int rt, LL val)    {        if (mult[rt])            mult[rt] = (mult[rt] * val) % mod;        else            mult[rt] = val;        add[rt] = (add[rt] * val) % mod;        LL sum1 = sum[rt][1];        LL sum2 = sum[rt][2];        LL sum3 = sum[rt][3];        sum[rt][1] = (sum1 * val) % mod;        sum[rt][2] = (sum2 * val * val) % mod;        sum[rt][3] = (sum3 * val * val * val) % mod;    }    void runSame(int rt, LL val)    {        same[rt] = val;        add[rt] = mult[rt] = 0;        sum[rt][1] = (val * sz[rt]) % mod;        sum[rt][2] = (val * val * sz[rt]) % mod;        sum[rt][3] = (val * val * val * sz[rt]) % mod;    }    void pushdown(int rt)    {        if (same[rt])        {            runSame(rt << 1, same[rt]);            runSame(rt << 1 | 1, same[rt]);            same[rt] = 0;        }        if (mult[rt])        {            runMult(rt << 1, mult[rt]);            runMult(rt << 1 | 1, mult[rt]);            mult[rt] = 0;        }        if (add[rt])        {            runAdd(rt << 1, add[rt]);            runAdd(rt << 1 | 1, add[rt]);            add[rt] = 0;        }    }    void update(int L, int R, int C, int op, int lo, int hi, int rt)    {        if (L <= lo && hi <= R)        {            if (op == 1)                runAdd(rt, C);            if (op == 2)                runMult(rt, C);            if (op == 3)                runSame(rt, C);            return;        }        pushdown(rt);        int mi = (lo + hi) >> 1;        if (L <= mi)            update(L, R, C, op, lson);        if (mi < R)            update(L, R, C, op, rson);        pushup(rt);    }    int query(int L, int R, int p, int lo, int hi, int rt)    {        if (L <= lo && hi <= R)        {            return sum[rt][p];        }        pushdown(rt);        int mi = (lo + hi) >> 1;        LL res = 0;        if (L <= mi)            res += query(L, R, p, lson);        if (mi < R)            res += query(L, R, p, rson);        pushup(rt);        return res % mod;    }} seg;int main(){#ifdef LOCAL    FIN;#endif // LOCAL    int n, m;    while (~scanf("%d%d", &n, &m))    {        if (!n && !m)            break;        seg.build(1, n, 1);        while (m--)        {            int op = readT();            int x = readT();            int y = readT();            int c = readT();            if (op != 4)                seg.update(x, y, c, op, 1, n, 1);            else                printf("%d\n", seg.query(x, y, c, 1, n, 1));        }    }    return 0;}



0 0