POJ 3468 Splay 解法

来源:互联网 发布:淘宝爆款打造花钱 编辑:程序博客网 时间:2024/05/02 19:45

题解

Splay入门模板
将l - 1移到根, r + 1移到根下方, 那么[l, r]就在根的右子树的左子树上, 更新的时候也这样旋转, 更新lazy


code:

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define debug 0#define M(a, b) memset(a, b, sizeof(a))#define ls ch[x][0]#define rs ch[x][1]const int maxn = (1e5 + 10);struct Splay{    int pre[maxn], ch[maxn][2], sz[maxn], v[maxn];    int add[maxn], a[maxn];    int root, rt;    long long sum[maxn];    Splay() {        root = rt = 0;        M(pre, 0);        M(ch, 0);        M(sz, 0);        M(v, 0);        M(sum, 0);        M(add, 0);    }    void newNode(int &x, int c) {//新建节点        x = ++rt;        sz[x] = 1;        v[x] = sum[x] = c;    }    void pushDown(int x) {//下移        if (add[x]) {            v[x] += add[x];            add[ls] += add[x];            add[rs] += add[x];            sum[ls] += (long long)sz[ls] * add[x];            sum[rs] += (long long )sz[rs] * add[x];            add[x] = 0;        }    }    void pushUp(int x) {//向上传递        sz[x] = sz[ls] + sz[rs] + 1;        sum[x] = sum[ls] + sum[rs] + v[x];    }    void Rotate(int x, int d) {//旋转        int y = pre[x];        pushDown(y);        pushDown(x);        ch[y][!d] = ch[x][d];        pre[ch[y][!d]] = y;        pre[x] = pre[y];        ch[x][d] = y;        if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;        pre[y] = x;        pushUp(y);    }    void splay(int x, int to) {//转到        while (pre[x] != to) {            if (pre[pre[x]] == to) Rotate(x, ch[pre[x]][0] == x);            else {                int y = pre[x], z = pre[y];                int f = (ch[z][1] == y);                if (ch[y][f] == x)                    Rotate(y, !f), Rotate(x, !f);                else                    Rotate(x, f), Rotate(x, !f);            }        }        pushUp(x);        if (!to) root = x;    }    void RotateTo(int k, int to) {        int x = root;        pushDown(x);        while (sz[ls] != k) {            if (sz[ls] < k) {                k -= sz[ls] + 1;                x = rs;            }            else {                x = ls;            }            pushDown(x);//要旋转在查找时要下移        }        splay(x, to);    }    void build(int &x, int l, int r, int f) {        if (l > r) return;        int mid = (l + r) >> 1;        newNode(x, a[mid]);        build(ls, l, mid - 1, x);        build(rs, mid + 1, r, x);        pre[x] = f;        pushUp(x);    }    void init(int n) {        newNode(root, -1);//加两个节点, 去除冗余信息        newNode(ch[root][1], -1);        pre[rt] = root;        sz[root] = 2;        for (int i = 0; i < n; ++i) scanf("%d", &a[i]);        build(ch[ch[root][1]][0], 0, n - 1, ch[root][1]);//建树, 保证中序遍历一致        pushUp(ch[root][1]);//传递        pushUp(root);    }    void update(int l, int r, int val) {        RotateTo(l - 1, 0);        RotateTo(r + 1, root);        add[ch[ch[root][1]][0]] += val;        sum[ch[ch[root][1]][0]] += (long long )val * sz[ch[ch[root][1]][0]];//[l, r]lazy    }    long long query(int l, int r) {        RotateTo(l - 1, 0);        RotateTo(r + 1, root);        return sum[ch[ch[root][1]][0]];    }}sp;int main() {#if debug    freopen("in.txt", "r", stdin);#endif //debug    //cin.tie(0);    //cin.sync_with_stdio(false);    int n, m, l, r, c;    char s[5];    while (~scanf("%d%d", &n, &m)) {        sp.init(n);        while (m--) {            scanf("%s%d%d", s, &l, &r);            if (s[0] == 'Q') printf("%I64d\n", sp.query(l, r));            else {                scanf("%d", &c);                sp.update(l, r, c);            }        }    }    return 0;}
0 0
原创粉丝点击