POJ3468--A Simple Problem with Integers(Splay Tree)

虽然有点难,但是这套题都挂了一个月了啊喂……

网上模板好多……最后还是抄了kuangbin聚聚的,毕竟好多模板都是抄他的,比较习惯……

POJ 3468

题意:给n个数,两种操作,区间整体加一个数,或者区间求和。

题解:把区间的前一个数挪到根,区间后一个数挪到根的右子树,根的右子树的左子树就是要处理的区间。。。

SplayTree是一个二叉排序树,它所保存的顺序是数字的编号,所以无论怎样旋转,编号的顺序都不会变。。。

在首尾各插入一个结点,这样求整个区间的时候也可以找到前一个数和后一个数。。。

照了别人的博客写了两遍,自己又裸敲一遍,还是错了好多细节,不过大概理解了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 100010;
int sz[N], ch[N][2], pre[N];
int a[N];
ll sum[N], add[N], key[N];
int root, tot;

void new_node(int &o, int fa, int k) {
    o = ++tot;
    sz[o] = 1;
    ch[o][0] = ch[o][1] = 0;
    pre[o] = fa;
    sum[o] = key[o] = k;
    add[o] = 0;
}

void push_up(int o) {
    sum[o] = sum[ch[o][0]] + sum[ch[o][1]] + key[o];
    sz[o] = sz[ch[o][0]] + sz[ch[o][1]] + 1; // +1 !!
}

void update(int o, int v) {
    if (!o) return ;
    add[o] += v;
    key[o] += v;
    sum[o] += (ll)sz[o]*v;
}

void push_down(int o) {
    if (add[o]) {
        update(ch[o][1], add[o]);
        update(ch[o][0], add[o]);
        add[o] = 0;
    }
}

void build(int &o, int l, int r, int fa) {
    if (l > r) return;
    int mid = (l+r) >> 1;
    new_node(o, fa, a[mid]);
    build(ch[o][0], l, mid-1, o);
    build(ch[o][1], mid+1, r, o);
    push_up(o);
}

void init(int n) {
    root = tot = 0;
    sz[0] = ch[0][0] = ch[0][1] = pre[0] = 0;
    sum[0] = add[0] = key[0] = 0;
    new_node(root, 0, -1);
    new_node(ch[root][1], root, -1);
    build(ch[ch[root][1]][0], 1, n, ch[root][1]);
    push_up(ch[root][1]);
    push_up(root);
}

void rotate(int o, int d) { // 0:left  1:right
    int fa = pre[o];
    push_down(fa);
    push_down(o);
    ch[fa][!d] = ch[o][d];
    pre[ch[o][d]] = fa;
    if (pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa] = o;
    pre[o] = pre[fa];
    ch[o][d] = fa;
    pre[fa] = o;
    push_up(fa);
}

void splay(int o, int goal) {
    push_down(o);
    while (pre[o] != goal) {
        if (pre[pre[o]] == goal) {
            rotate(o, ch[pre[o]][0] == o);
        } else {
            int fa = pre[o];
            int d = (ch[pre[fa]][0] == fa);
            if (ch[fa][d] == o) {
                rotate(o, !d);
                rotate(o, d);
            } else {
                rotate(fa, d);
                rotate(o, d);
            }
        }
    }
    push_up(o);
    if (goal == 0) root = o;
}

int get_kth(int o, int k) {
    push_down(o); //!!
    int t = sz[ch[o][0]] + 1;
    if (t == k) return o;
    if (t > k) return get_kth(ch[o][0], k);
    return get_kth(ch[o][1], k-t);
}

ll query(int l, int r) {
    splay(get_kth(root, l), 0);
    splay(get_kth(root, r+2), root);
    return sum[ ch[ch[root][1]][0] ];
}

void Add(int l, int r, int v) {
    splay(get_kth(root, l), 0);
    splay(get_kth(root, r+2), root);
    update(ch[ch[root][1]][0], v);
    push_up(ch[root][1]);
    push_up(root);
}

int main() {
    //freopen("in.txt", "r", stdin);
    int n, q;
    while (~scanf("%d%d", &n, &q) && n) {
        for (int i = 1; i <= n; ++i) scanf("%d", a+i);
        init(n);
        char op[2];
        int x, y, z;
        while (q--) {
            scanf("%s%d%d", op, &x, &y);
            if (*op == ‘Q‘) {
                printf("%lld\n", query(x, y));
            } else {
                scanf("%d", &z);
                Add(x, y, z);
            }
        }
    }
    return 0;
}
时间: 2024-10-24 13:35:58

POJ3468--A Simple Problem with Integers(Splay Tree)的相关文章

POJ3468 A Simple Problem with Integers ( 线段树)

题目: A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 55817   Accepted: 16839 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One typ

ACM学习历程——POJ3468 A Simple Problem with Integers(线段树)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

POJ - 3468 A Simple Problem with Integers (区间求和)

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

POJ-3468 A Simple Problem with Integers(线段树、段变化+段查询、模板)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 116441   Accepted: 36178 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o

poj3468 A Simple Problem with Integers (树状数组做法)

题目传送门 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 142198   Accepted: 44136 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One

bzoj3212: Pku3468 A Simple Problem with Integers(线段树)

3212: Pku3468 A Simple Problem with Integers 题目:传送门 题解: 感谢Rose_max大佬的倾情相(推)助(水题) 一起打线段树啊~~~~ 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 type

Poj(3468)——A Simple Problem with Integers(线段树)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 72424   Accepted: 22343 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ-3468 - A Simple Problem with Integers(线段树区间更新模板)

http://poj.org/problem?id=3468 Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of