首页 > 代码库 > BZOJ1503 NOI2004 郁闷的出纳员 平衡树

BZOJ1503 NOI2004 郁闷的出纳员 平衡树

题意:开始时给定一个空的数列,要求维护:1、加入一个数  2、数列中所有元素+k  3、数列中所有元素-k  4、查询数列中的第k大。其中对于任意时刻,如果有一个元素<Min,则删除该元素。

题解:平衡树裸题……话说当年还打算把Splay Treap SBT都学一下,结果现在只会Splay了QAQ

技术分享
#include <cstdio>#include <cstring>#include <cstdlib>#include <climits>#include <iostream>#include <algorithm>using namespace std;#define Pushup(x) tree[x].cnt=tree[tree[x].child[0]].cnt+tree[tree[x].child[1]].cnt+1const int MAXN=200000+2;struct NODE{    int value,cnt,child[2];}tree[MAXN];int N,Min,cnt,root,add;char Order[2];void Rotate(int &x,bool type){    int y=tree[x].child[!type];    tree[x].child[!type]=tree[y].child[type],tree[y].child[type]=x;    tree[y].cnt=tree[x].cnt,Pushup(x);    x=y;}void Maintain(int &x,bool type){    if(tree[tree[tree[x].child[type]].child[type]].cnt>tree[tree[x].child[!type]].cnt) Rotate(x,!type);    else if(tree[tree[tree[x].child[type]].child[!type]].cnt>tree[tree[x].child[!type]].cnt) Rotate(tree[x].child[type],type),Rotate(x,!type);    else return;    Maintain(tree[x].child[0],false),Maintain(tree[x].child[1],true);    Maintain(x,true),Maintain(x,false);}void Insert(int &x,int value){    if(x){        tree[x].cnt++;        if(value<tree[x].value) Insert(tree[x].child[0],value);        else Insert(tree[x].child[1],value);        Maintain(x,value>=tree[x].value);    }    else{        x=++cnt;        tree[x].child[0]=tree[x].child[1]=0;        tree[x].cnt=1,tree[x].value=http://www.mamicode.com/value;    }}void Delete(int &x,int v,int minv){    if(!x) return;    if(tree[x].value+v<minv) Delete(x=tree[x].child[1],v,minv);    else{        Delete(tree[x].child[0],v,minv);        Pushup(x);    }}int Select(int &x,int k){    int c=tree[tree[x].child[1]].cnt+1;    if(c==k) return tree[x].value;    else if(c<k) return Select(tree[x].child[0],k-c);    else return Select(tree[x].child[1],k);}int main(){    cin >> N >> Min;    for(int k,t;N--;){        scanf("%s %d",Order,&k);        if(Order[0]==I && k>=Min) Insert(root,k-add);        if(Order[0]==A) add+=k;        if(Order[0]==S) add-=k,Delete(root,add,Min);        if(Order[0]==F) cout << (k>tree[root].cnt?-1:Select(root,k)+add) << endl;    }    cout << cnt-tree[root].cnt << endl;    return 0;}
View Code

 

BZOJ1503 NOI2004 郁闷的出纳员 平衡树