洛谷 P1486 BZOJ 1503 NOI 2004 郁闷的出纳员 fhq treap

思路:

1. 此处的fhq treap的分裂是按照权值分裂然后插入的。将小于k的分为一棵子树,大于等于k的分为另一棵子树。

2. 删除的时候只要将大于等于min的分裂到以root为根的树中,另一部分不用管,扔掉。

3. 维护一个加标记,注意不要忘记某个地方的pushdown和pushup

其他就是fhq treap的基本操作了

#include<bits/stdc++.h>
using namespace std;
#define ls a[x].l
#define rs a[x].r
const int N = 1e5 + 10;
int root, tot, ans;
struct tree{
    int l, r, atag, val, dat, siz;
}a[N];
struct fhq_treap{
    void newnode(int &x, int val){
        a[x = ++tot].dat = rand(); a[x].siz = 1; a[x].val = val;
    }
    void addone(int x, int val){
        if(!x) return;
        a[x].val += val; a[x].atag += val;
    }
    void up(int x){
        if(!x) return ;
        a[x].siz = a[ls].siz + a[rs].siz + 1;
    }
    void down(int x){
        if(!x) return;
        if(a[x].atag) addone(ls, a[x].atag), addone(rs, a[x].atag);
        a[x].atag = 0;
    }
    void Merge(int &x, int l, int r){
        if(!l || !r) x = l + r;
        else if(a[l].dat < a[r].dat) down(x = l), Merge(rs, rs, r), up(x);
        else down(x = r), Merge(ls, l, ls), up(x);
    }
    void split(int x, int k, int &l, int &r){
        if(!x) l = r = 0;
        else{
            down(x);
            if(a[x].val < k) l = x, split(rs, k, rs, r);
            else r = x, split(ls, k, l, ls);
        }
        up(x);
    }
    void ins(int val){
        int x;
        newnode(x, val);
        int l, r;
        split(root, val, l, r); Merge(l, l, x); Merge(root, l, r);
    }
    int getval(int x, int rank){
        if(x == 0) return -1;
        down(x);
        if(a[rs].siz >= rank) return getval(rs, rank);
        if(a[rs].siz + 1 >= rank) return a[x].val;
        return getval(ls, rank - a[rs].siz - 1);
    }
    void del(int val){
        int l;
        split(root, val, l, root);
    }
}treap;
int n, lim, k;
char ch[5];
int main(){
    scanf("%d%d", &n, &lim);
    while(n--){
        scanf("%s%d", ch, &k);
        if(ch[0] == 'I'){
            if(k >= lim) treap.ins(k), ans++;
        } 
        else if(ch[0] == 'A') treap.addone(root, k);
        else if(ch[0] == 'S') treap.addone(root, -k), treap.del(lim);
        else printf("%d\n", treap.getval(root, k));
    }
    printf("%d\n", ans - a[root].siz);
    return 0;
}
View Code

 

posted @ 2018-04-21 23:12  Ror_shach  阅读(373)  评论(0编辑  收藏  举报