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+1 const 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=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; }