[NOI2004]郁闷的出纳员
题目大意:
给定$n(n\leq100000)$和$min$,按照给定的顺序进行以下操作共$n$次:
1.加入一个数;
2.把所有数加上$x$;
3.把所有数减去$x$,并把小于$min$的数删去;
4.询问第$k$大数。
思路:
Splay。区间加减可以用tag实现,删数可以通过把大于等于$min$的最小数提到根,然后删除左子树。
1 #include<cstdio> 2 #include<cctype> 3 #include<climits> 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 inline char getalpha() { 12 register char ch; 13 while(!isalpha(ch=getchar())); 14 return ch; 15 } 16 const int N=100001; 17 int ext; 18 class SplayTree { 19 private: 20 int val[N],size[N],tag[N],par[N],ch[N][2],root,cnt; 21 int sz,new_node(const int &x) { 22 val[++sz]=x; 23 size[sz]=1; 24 return sz; 25 } 26 void push_up(const int &p) { 27 size[p]=size[ch[p][0]]+size[ch[p][1]]+1; 28 } 29 void push_down(const int &p) { 30 if(ch[p][0]) { 31 tag[ch[p][0]]+=tag[p]; 32 val[ch[p][0]]+=tag[p]; 33 } 34 if(ch[p][1]) { 35 tag[ch[p][1]]+=tag[p]; 36 val[ch[p][1]]+=tag[p]; 37 } 38 tag[p]=0; 39 } 40 void rotate(const int &x) { 41 const int y=par[x],z=par[y]; 42 const bool b=x==ch[y][0]; 43 push_down(y),push_down(x); 44 par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x; 45 par[ch[z][y==ch[z][1]]=x]=z; 46 push_up(y),push_up(x); 47 } 48 void splay(int x,const int &goal) { 49 for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) { 50 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y); 51 } 52 if(!goal) root=x; 53 } 54 public: 55 SplayTree() { 56 root=ch[0][1]=new_node(INT_MAX>>1); 57 } 58 void insert(const int &x) { 59 int y=root; 60 while(ch[y][x>val[y]]) { 61 push_down(y); 62 y=ch[y][x>val[y]]; 63 } 64 push_down(y); 65 par[ch[y][x>val[y]]=new_node(x)]=y; 66 splay(y,0); 67 cnt++; 68 } 69 void modify(const int &x) { 70 tag[root]+=x; 71 val[root]+=x; 72 } 73 void erase(const int &min) { 74 int tmp=0; 75 for(register int y=root;y;y=ch[y][min>val[y]]) { 76 push_down(y); 77 if(val[y]>=min) tmp=y; 78 } 79 if(!tmp) return; 80 splay(tmp,0); 81 if(!ch[tmp][0]) return; 82 ext+=size[ch[tmp][0]]; 83 size[tmp]-=size[ch[tmp][0]]; 84 cnt-=size[ch[tmp][0]]; 85 ch[tmp][0]=0; 86 } 87 int find(int x) { 88 if(x>cnt) return -1; 89 for(register int y=root;;y=ch[y][size[ch[y][1]]>x]) { 90 push_down(y); 91 if(par[y]&&y==ch[par[y]][0]) x-=size[ch[par[y]][1]]+1; 92 if(size[ch[y][1]]==x) return val[y]; 93 } 94 } 95 }; 96 SplayTree t; 97 int main() { 98 for(register int i=getint(),min=getint();i;i--) { 99 const char opt=getalpha(); 100 const int x=getint(); 101 if(opt=='I') { 102 if(x>=min) t.insert(x); 103 } 104 if(opt=='A') t.modify(x); 105 if(opt=='S') { 106 t.modify(-x); 107 t.erase(min); 108 } 109 if(opt=='F') printf("%d\n",t.find(x)); 110 } 111 printf("%d\n",ext); 112 return 0; 113 }