zoukankan      html  css  js  c++  java
  • 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
    ", query(x, y));
                } else {
                    scanf("%d", &z);
                    Add(x, y, z);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    网络攻击技术:SQL Injection(sql注入)
    人生若只如初见,何事秋风悲画扇
    TCPClient、TCPListener的用法
    C#中时间的Ticks属性
    string.Empty、" "、null 三者之间的区别
    telnet的使用解析
    public DataTable ExecuteQuery(string sql) 这段话具体意思
    C#中三层架构UI、BLL、DAL、Model详解(送给自学的初学者)
    数据库三层架构
    获取SQL Server数据库的表结构的做法
  • 原文地址:https://www.cnblogs.com/wenruo/p/5830353.html
Copyright © 2011-2022 走看看