[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 }

 

posted @ 2018-03-06 10:25  skylee03  阅读(111)  评论(0编辑  收藏  举报