• 模板


    来自这个神仙的https://www.luogu.org/space/show?uid=56230

    终于明白了Treap,不知道是因为有了足够的积累了吗?

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    
    const int MAXN = 1000000;
    
    int na;
    int ch[MAXN + 5][2];
    int val[MAXN + 5], dat[MAXN + 5];
    int siz[MAXN + 5], cnt[MAXN + 5];
    int tot, root;
    
    inline void Init() {
        tot = 0;
        root = 0;
    }
    
    inline int NewNode(int v) {
        val[++tot] = v, dat[tot] = rand();
        ch[tot][0] = ch[tot][1] = 0;
        siz[tot] = 1, cnt[tot] = 1;
        return tot;
    }
    
    inline void PushUp(int id) {
        siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[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);
    }
    
    inline void Insert(int &id, int v) {
        if(!id)
            id = NewNode(v);
        else {
            if(v == val[id])
                ++cnt[id];
            else {
                int d = v < val[id] ? 0 : 1;
                Insert(ch[id][d], v);
                if(dat[id] < dat[ch[id][d]])
                    Rotate(id, d ^ 1);
            }
            PushUp(id);
        }
    }
    
    void Remove(int &id, int v) {
        if(!id)
            return;
        else {
            if(v == val[id]) {
                if(cnt[id] > 1) {
                    cnt[id]--;
                    PushUp(id);
                } else if(ch[id][0] || ch[id][1]) {
                    if(!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]])
                        Rotate(id, 1), Remove(ch[id][1], v);
                    else
                        Rotate(id, 0), Remove(ch[id][0], v);
                    PushUp(id);
                } else
                    id = 0;
            } else {
                v < val[id] ? Remove(ch[id][0], v) : Remove(ch[id][1], v);
                PushUp(id);
            }
        }
    }
    
    int GetRank(int id, int v) {
        if(!id)
            return 0;
        else {
            if(v == val[id])
                return siz[ch[id][0]] + 1;
            else if(v < val[id])
                return GetRank(ch[id][0], v);
            else
                return siz[ch[id][0]] + cnt[id] + GetRank(ch[id][1], v);
        }
    }
    
    int GetValue(int id, int rk) {
        if(!id)
            return -1;
        else {
            if(rk <= siz[ch[id][0]])
                return GetValue(ch[id][0], rk);
            else if(rk <= siz[ch[id][0]] + cnt[id])
                return val[id];
            else
                return GetValue(ch[id][1], rk - siz[ch[id][0]] - cnt[id]);
        }
    }
    
    int GetPrev(int v) {
        int id = root, prev = -1;
        while(id) {
            if(val[id] < v)
                prev = val[id], id = ch[id][1];
            else
                id = ch[id][0];
        }
        return prev;
    }
    
    int GetNext(int v) {
        int id = root, next = -1;
        while(id) {
            if(val[id] > v)
                next = val[id], id = ch[id][0];
            else
                id = ch[id][1];
        }
        return next;
    }
    
    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);
            else if(op == 2)
                Remove(root, x);
            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(x));
            else if(op == 6)
                printf("%d
    ", GetNext(x));
        }
        return 0;
    }
    

    那么就再也不需要什么对顶堆了,平衡树最多也就浪费一点空间。
    https://www.luogu.org/problem/P3871
    https://www.luogu.org/problem/P1801

    所以说类似找排名的思想,可以找出树中的前k大的和,前k小的和,或者奇奇怪怪的其他值。也可以像之前那样加入限定,找小于v的至多k个和,每找一个还减掉一个v,总之非常灵活。
    下面是找前k小的和的办法。

    const int MAXN = 200005;
    
    int ch[MAXN][2];
    int val[MAXN], dat[MAXN];
    ll siz[MAXN], cnt[MAXN];
    ll sum[MAXN];
    int tot, root;
    
    inline void Init() {
        tot = 0;
        root = 0;
    }
    
    inline int NewNode(int v, ll num) {
        ch[++tot][0] = ch[tot][1] = 0;
        val[tot] = v, dat[tot] = rand();
        siz[tot] = cnt[tot] = num;
        sum[tot] = 1ll * val[tot] * cnt[tot];
        return tot;
    }
    
    inline void PushUp(int id) {
        siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[id];
        sum[id] = sum[ch[id][0]] + sum[ch[id][1]] + 1ll * val[id] * cnt[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);
    }
    
    inline void Insert(int &id, int v, ll num) {
        if(!id)
            id = NewNode(v, num);
        else {
            if(v == val[id])
                cnt[id] += num;
            else {
                int d = v < val[id] ? 0 : 1;
                Insert(ch[id][d], v, num);
                if(dat[id] < dat[ch[id][d]])
                    Rotate(id, d ^ 1);
            }
            PushUp(id);
        }
    }
    
    ll GetSum(int id, ll k) {
        if(!id||k<=0)
            return 0;
        else {
            if(k >= siz[ch[id][0]] + cnt[id])
                return GetSum(ch[id][1], k - siz[ch[id][0]] - cnt[id]) + sum[ch[id][0]] + 1ll * val[id] * cnt[id];
            else if(k >= siz[ch[id][0]])
                return sum[ch[id][0]] + 1ll * val[id] * (k - siz[ch[id][0]]);
            else
                return GetSum(ch[id][0], k);
        }
    }
    
  • 相关阅读:
    用户代理列表--爬虫伪装浏览器访问用
    python爬虫解析页面数据的三种方式
    requests模块的使用
    Python pip源更改
    个人博客项目开发
    Django之中间件
    Django之发送邮件
    Django组件之用户认证组件
    Django之Cookie与session
    Django组件之分页器
  • 原文地址:https://www.cnblogs.com/Yinku/p/11280142.html
Copyright © 2020-2023  润新知