[NOI2004]郁闷的出纳员
题目大意:
给定$n(n\leq100000)$和$min$,按照给定的顺序进行以下操作共$n$次:
1.加入一个数;
2.把所有数加上$x$;
3.把所有数减去$x$,并把小于$min$的数删去;
4.询问第$k$大数。
思路:
Splay。区间加减可以用tag实现,删数可以通过把大于等于$min$的最小数提到根,然后删除左子树。
#include<cstdio> #include<cctype> #include<climits> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } inline char getalpha() { register char ch; while(!isalpha(ch=getchar())); return ch; } const int N=100001; int ext; class SplayTree { private: int val ,size ,tag ,par ,ch [2],root,cnt; int sz,new_node(const int &x) { val[++sz]=x; size[sz]=1; return sz; } void push_up(const int &p) { size[p]=size[ch[p][0]]+size[ch[p][1]]+1; } void push_down(const int &p) { if(ch[p][0]) { tag[ch[p][0]]+=tag[p]; val[ch[p][0]]+=tag[p]; } if(ch[p][1]) { tag[ch[p][1]]+=tag[p]; val[ch[p][1]]+=tag[p]; } tag[p]=0; } void rotate(const int &x) { const int y=par[x],z=par[y]; const bool b=x==ch[y][0]; push_down(y),push_down(x); par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x; par[ch[z][y==ch[z][1]]=x]=z; push_up(y),push_up(x); } void splay(int x,const int &goal) { for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) { if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y); } if(!goal) root=x; } public: SplayTree() { root=ch[0][1]=new_node(INT_MAX>>1); } void insert(const int &x) { int y=root; while(ch[y][x>val[y]]) { push_down(y); y=ch[y][x>val[y]]; } push_down(y); par[ch[y][x>val[y]]=new_node(x)]=y; splay(y,0); cnt++; } void modify(const int &x) { tag[root]+=x; val[root]+=x; } void erase(const int &min) { int tmp=0; for(register int y=root;y;y=ch[y][min>val[y]]) { push_down(y); if(val[y]>=min) tmp=y; } if(!tmp) return; splay(tmp,0); if(!ch[tmp][0]) return; ext+=size[ch[tmp][0]]; size[tmp]-=size[ch[tmp][0]]; cnt-=size[ch[tmp][0]]; ch[tmp][0]=0; } int find(int x) { if(x>cnt) return -1; for(register int y=root;;y=ch[y][size[ch[y][1]]>x]) { push_down(y); if(par[y]&&y==ch[par[y]][0]) x-=size[ch[par[y]][1]]+1; if(size[ch[y][1]]==x) return val[y]; } } }; SplayTree t; int main() { for(register int i=getint(),min=getint();i;i--) { const char opt=getalpha(); const int x=getint(); if(opt=='I') { if(x>=min) t.insert(x); } if(opt=='A') t.modify(x); if(opt=='S') { t.modify(-x); t.erase(min); } if(opt=='F') printf("%d\n",t.find(x)); } printf("%d\n",ext); return 0; }
- 【NOI2004】郁闷的出纳员Splay版
- 【BZOJ1503】[NOI2004]郁闷的出纳员
- BZOJ 1503: [NOI2004]郁闷的出纳员 splay
- [NOI2004]郁闷的出纳员
- 【bzoj 1503】 [NOI2004]郁闷的出纳员
- 【Treap/非旋转Treap】BZOJ1503 [NOI2004]郁闷的出纳员
- BZOJ 1503 郁闷的出纳员(平衡树)(NOI 2004)
- 【NOI2004】郁闷的出纳员Codevs1286
- bzoj 1503 [NOI2004]郁闷的出纳员 平衡树(treap/Splay)
- BZOJ1503 [NOI2004]郁闷的出纳员
- noi2004-郁闷的出纳员(cashier) 解题报告
- 【NOI2004】郁闷的出纳员 // SPLAY TREE
- 【BZOJ1503】【NOI2004】郁闷的出纳员
- BZOJ 1503: [NOI2004]郁闷的出纳员
- 【BZOJ】1503: [NOI2004]郁闷的出纳员(Splay)
- NOI2004 郁闷的出纳员
- 【NOI2004】郁闷的出纳员 平衡树
- [NOI2004]郁闷的出纳员(Treap)
- NOI 2004 郁闷的出纳员
- 【BZOJ 1503】【NOI 2004】郁闷的出纳员