标签:
#include"iostream" #include"cstdio" using namespace std; int key[400000],sum[400000]={0},cnt[400000]={0},pre[400000],ch[400000][2]; //key是这个节点的值 //sum表示这个点有多少子树,cnt表示这个点出现了几次,pre表示这个点的父节点,ch代表左右孩子 int n,mi,de=0,root=0,tot=0; int ans=0; void newnode(int &num,int fa,int k) { num=++tot; key[num]=k; sum[num]=cnt[num]=1; pre[num]=fa; ch[num][0]=ch[num][1]=0;//ch里面存的也就是对应子树的num值 return; } void rotate(int x,int kind)//kind表示x是y的什么子树,0是左子树,1是右子树 { int y=pre[x];//y是x的父亲节点 ch[y][kind]=ch[x][!kind];//x离开了,那么x的位置由x的相反位置的子树代替 pre[ch[x][!kind]]=y; if (pre[y]) ch[pre[y]][key[pre[y]] pre[x]=pre[y]; pre[y]=x; ch[x][!kind]=y; sum[y]=sum[ch[y][0]]+sum[ch[y][1]]+cnt[y]; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+cnt[x]; return; } int search(int k) { int x=root; while(ch[x][key[x] { if (key[x]==k) return x; x=ch[x][key[x] } return x; } void splay(int x) //把节点x抖到根 { while (pre[x]!=0)//没到根的时候 { int y=pre[x]; if (pre[y]==0) rotate(x,ch[y][1]==x); //如果y就是根结点,旋转一次就行了。判断y的右子树是不是x,返回恰好是x的子树类型 else { int z=pre[y];//z是x的祖父 int kind=(y==ch[z][1]); //kind表示y和z的关系 int kind2=(x==ch[y][1]); //kind2表示x和y的关系 if (kind==kind2) { rotate(y,kind); rotate(x,kind2); }//一字型旋转 else { rotate(x,kind2); rotate(x,kind); }//之字形旋转 } } root=x; return; } void Insert(int k) { if (root==0) { newnode(root,0,k); return; } splay(search(k));//找到跟k相近的节点并“抖”到根上,好插~ if (key[root]==k) { sum[root]++; cnt[root]++; return; } int sp=0;//species,记录是根结点的左子树还是右子树 if (key[root] int rec=ch[root][sp];//record记录原来的子树 newnode(ch[root][sp],root,k);//新点加入 int x=ch[root][sp];//x是新点 ch[x][sp]=rec;//新点的子树是y,且子树应该是相同类型 pre[rec]=x; sum[x]=sum[rec]+cnt[x]; sum[root]+=cnt[x]; splay(x); } void Delete() { Insert(mi-de-1);//插入一个基本工资减去之前别的人加的工资数的人用来判断。 //在这个题目中,通过插入这个点来把比他工资少(也就是工资小于基本工资)的人删掉 ans+=sum[root]-sum[ch[root][1]]-1;//ans是离开公司的人数 root=ch[root][1];//右子树是还在公司里的 pre[root]=0; } int Find(int ask) { if (ask>sum[root]) return -1; ask=sum[root]-ask+1; int x=root; while (ask>0) { if (ask>sum[ch[x][0]]+cnt[x]) {ask=ask-sum[ch[x][0]]-cnt[x]; x=ch[x][1]; continue;} if (ask<=sum[ch[x][0]]+cnt[x] && ask>sum[ch[x][0]]) { splay(x); return key[x]+de; } x=ch[x][0]; } } int main() { cin >> n >> mi; de=0; char a; int b; scanf("%c",&a); for(int i=1; i<=n; i++) { char a; int b; scanf("%c %d",&a,&b); if(a==‘I‘ && b>=mi) Insert(b-de); if(a==‘A‘) de+=b; if(a==‘S‘) {de-=b;Delete();} if(a==‘F‘) {cout<<Find(b)<<endl;} scanf("%c",&a); } cout << ans << endl; return 0; }
标签:
原文地址:http://www.cnblogs.com/Shymuel/p/4393567.html