您的位置:首页 > 其它

UVA 12436 Rip Van Winkle's Code(线段树区间更新)

2015-07-31 16:09 253 查看

题意:

对于长度为250000的区间,给了你四种操作:

操作A,从st到ed这段区间内的数,分别加上1,2,…,st-ed+1。

操作B,从st到ed这段区间内的数,分别加上,st-ed+1,st-ed,…,1。

操作C,将st到ed这段区间内的数赋值成x。

操作S,查询st到ed的这段区间内的数的总和。

解析:

因为操作A和操作B都是操作的实际上都是等差数列,所以可以一起考虑。

对于操作AB,在线段树的结点中记录了这个区间的首项a1,同时记录了这段区间内的公差d。

对于操作C,在线段树的结点内,用一个cover表示当前区间内的数是否全部相同,并且还用一个val表示如果在区间里的数完全相同的时候,即cover=1时,这个数是多少。


容易得到,等差数列相加还是等差数列,所以可以对一个区间进行多次的AB操作。

对于C操作,因为强制将区间内的赋值成x,所以之前的AB操作全部失效,即这时候应该把表示AB操作的几个变量,a1和d全部赋值为零。

当向子区间传递记录的值的时候,应该优先C操作的标记,因为当操作AB和操作C的标记同时存在的时候,一定是发生在先进行了操作C,再进行了操作AB。

mymy codecode

[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;
typedef long long ll;
const int N = 250001;

struct Node {
    int L, R;
    ll a1, d, val, sum;
    bool cover;
    Node() { a1 = d = val = sum = cover = 0;}
    ll length() { return R - L + 1; }
} node[N<<2];

void pushUp(int o) {
    node[o].sum = node[ls].sum + node[rs].sum;
}

void pushDown(int o) {
    if(node[o].cover) {
        node[ls].cover = node[rs].cover = true;
        node[ls].val = node[rs].val = node[o].val;
        node[ls].sum = node[ls].length() * node[o].val;
        node[rs].sum = node[rs].length() * node[o].val;
        node[ls].a1 = node[ls].d = node[rs].a1 = node[rs].d = 0;
        node[o].val = node[o].cover = 0;
    }
    if(node[o].a1 || node[o].d) {
        ll d = node[o].d;
        ll len1 = node[ls].length(), len2 = node[rs].length();
        ll a1 = node[o].a1, a2 = a1 + len1 * d;

        node[ls].a1 += a1;
        node[ls].d += d;
        node[ls].sum += a1 * len1 + len1 * (len1-1)/2 * d;

        node[rs].a1 += a2;
        node[rs].d += d;
        node[rs].sum += a2 * len2 + len2 * (len2-1)/2 * d;

        node[o].a1 = node[o].d = 0;
    }
}

void build(int o, int L, int R) {
    node[o] = Node();
    node[o].L = L, node[o].R = R;
    if(L == R) return ;
    int M = (L + R)/2;
    build(lson);
    build(rson);
    pushUp(o);
}

void modify(int o, int L, int R, int ql, int qr, ll d) {
    if(ql <= L && R <= qr) {
        ll a1 = (d == 1) ? (L - ql + 1) : (qr - L + 1);
        ll n = node[o].length();
        node[o].a1 += a1;
        node[o].d += d;
        node[o].sum += a1 * n + n * (n-1)/2 * d;
        return ;
    }
    pushDown(o);
    int M = (L + R)/2;
    if(ql <= M) modify(lson, ql, qr, d);
    if(qr > M) modify(rson, ql, qr, d);
    pushUp(o);
}

void setValue(int o, int L, int R, int ql, int qr, ll val) {
    if(ql <= L && R <= qr) {
        node[o].sum = node[o].length() * val;
        node[o].val = val;
        node[o].cover = true;
        node[o].a1 = node[o].d = 0;
        return ;
    }
    pushDown(o);
    int M = (L + R)/2;
    if(ql <= M) setValue(lson, ql, qr, val);
    if(qr > M) setValue(rson, ql, qr, val);
    pushUp(o);
}

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

int main() {
    build(1, 1, N);
    int T;
    scanf("%d", &T);
    char oper[5];
    int ql, qr, val;
    while(T--) {
        scanf("%s%d%d", oper, &ql, &qr);
        if(oper[0] == 'A') {
            modify(1, 1, N, ql, qr, 1);
        }else if(oper[0] == 'B') {
            modify(1, 1, N, ql, qr, -1);
        }else if(oper[0] == 'C') {
            scanf("%d", &val);
            setValue(1, 1, N, ql, qr, val);
        }else if(oper[0] == 'S') {
            printf("%lld\n", query(1, 1, N, ql, qr));
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: