zoukankan      html  css  js  c++  java
  • 模板

    鉴于水平有限,可能会有问题。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define ls ch[id][0]
    #define rs ch[id][1]
    
    const int INF = 1e9;
    
    const int MAXN = 1000000 + 5;
    int ch[MAXN][2], dat[MAXN];
    
    int val[MAXN];
    int cnt[MAXN];
    int siz[MAXN];
    ll sum[MAXN];
    
    int tot, root;
    
    inline void Init() {
        tot = 0;
        root = 0;
    }
    
    inline int NewNode(int v, int num) {
        int id = ++tot;
        ls = rs = 0;
        dat[id] = rand();
        val[id] = v;
        cnt[id] = num;
        siz[id] = num;
        sum[id] = 1ll * num * v;
        return id;
    }
    
    inline void PushUp(int id) {
        siz[id] = siz[ls] + siz[rs] + cnt[id];
        sum[id] = sum[ls] + sum[rs] + 1ll * cnt[id] * val[id];
    }
    
    inline void Rotate(int &id, int d) {
        int temp = ch[id][d ^ 1];
        ch[id][d ^ 1] = ch[temp][d];
        ch[temp][d] = id;
        id = temp;
        PushUp(ch[id][d]);
        PushUp(id);
    }
    
    //插入num个v
    inline void Insert(int &id, int v, int num) {
        if(!id)
            id = NewNode(v, num);
        else {
            if(v == val[id])
                cnt[id] += num;
            else {
                int d = val[id] > v ? 0 : 1;
                Insert(ch[id][d], v, num);
                if(dat[id] < dat[ch[id][d]])
                    Rotate(id, d ^ 1);
            }
            PushUp(id);
        }
    }
    
    //删除至多num个v
    void Remove(int &id, int v, int num) {
        if(!id)
            return;
        else {
            if(v == val[id]) {
                if(cnt[id] > num) {
                    cnt[id] -= num;
                    PushUp(id);
                } else if(ls || rs) {
                    if(!rs || dat[ls] > dat[rs])
                        Rotate(id, 1), Remove(rs, v, num);
                    else
                        Rotate(id, 0), Remove(ls, v, num);
                    PushUp(id);
                } else
                    id = 0;
            } else {
                val[id] > v ? Remove(ls, v, num) : Remove(rs, v, num);
                PushUp(id);
            }
        }
    }
    
    //查询v的排名,排名定义为<v的数的个数+1。
    int GetRank(int id, int v) {
        int res = 1;
        while(id) {
            if(val[id] > v)
                id = ls;
            else if(val[id] == v) {
                res += siz[ls];
                break;
            } else {
                res += siz[ls] + cnt[id];
                id = rs;
            }
        }
        return res;
    }
    
    //查询排名为rk的数,rk必须是正整数,rk过大返回无穷
    int GetValue(int id, int rk) {
        int res = INF;
        while(id) {
            if(siz[ls] >= rk)
                id = ls;
            else if(siz[ls] + cnt[id] >= rk) {
                res = val[id];
                break;
            } else {
                rk -= siz[ls] + cnt[id];
                id = rs;
            }
        }
        return res;
    }
    
    //查询v的前驱的值(<v的第一个节点的值),不存在前驱返回负无穷
    int GetPrev(int id, int v) {
        int res = -INF;
        while(id) {
            if(val[id] < v)
                res = val[id], id = rs;
            else
                id = ls;
        }
        return res;
    }
    
    //查询v的后继的值(>v的第一个节点的值),不存在后继返回无穷
    int GetNext(int id, int v) {
        int res = INF;
        while(id) {
            if(val[id] > v)
                res = val[id], id = ls;
            else
                id = rs;
        }
        return res;
    }
    
    //查询小于等于v的数的和
    ll GetSumValue(int id, int v) {
        ll res = 0;
        while(id) {
            if(val[id] > v)
                id = ls;
            else if(val[id] == v) {
                res += sum[ls] + 1ll * cnt[id] * val[id];
                break;
            } else {
                res += sum[ls] + 1ll * cnt[id] * val[id];
                id = rs;
            }
        }
        return res;
    }
    
    //查询前rk个数的和,rk必须是正整数
    ll GetSumRank(int id, int rk) {
        ll res = 0;
        while(id) {
            if(siz[ls] >= rk)
                id = ls;
            else if(siz[ls] + cnt[id] >= rk) {
                res += sum[ls] + 1ll * (rk - siz[ls]) * val[id];
                break;
            } else {
                res += sum[ls] + 1ll * cnt[id] * val[id];
                rk -= siz[ls] + cnt[id];
                id = rs;
            }
        }
        return res;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        Init();
        int ops;
        scanf("%d", &ops);
        for(int i = 1; i <= ops; i++) {
            int op, x;
            scanf("%d%d", &op, &x);
            if(op == 1)
                Insert(root, x, 1);
            else if(op == 2)
                Remove(root, x, 1);
            else if(op == 3)
                printf("%d
    ", GetRank(root, x));
            else if(op == 4)
                printf("%d
    ", GetValue(root, x));
            else if(op == 5)
                printf("%d
    ", GetPrev(root, x));
            else if(op == 6)
                printf("%d
    ", GetNext(root, x));
            else if(op == 7)
                printf("%lld
    ", GetSumRank(root, x));
            else if(op == 8)
                printf("%lld
    ", GetSumValue(root, x));
        }
        return 0;
    }
    
  • 相关阅读:
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十一)
    install ubuntu on Android mobile phone
    Mac OS, Mac OSX 与Darwin
    About darwin OS
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十)
    Linux下编译安装qemu和libvirt
    libvirt(virsh命令总结)
    深入浅出 kvm qemu libvirt
    自然语言交流系统 phxnet团队 创新实训 项目博客 (九)
    自然语言交流系统 phxnet团队 创新实训 项目博客 (八)
  • 原文地址:https://www.cnblogs.com/Inko/p/11403359.html
Copyright © 2011-2022 走看看