您的位置:首页 > 其它

[NOI2004]郁闷的出纳员

2018-03-06 10:25 211 查看

题目大意:
  给定$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

=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; }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: