大致题意就是对初始为空的数列的各种操作233
题解:Splay啦~
其中可能会遇到的几个问题:
#1.如何删去低于min的点:
找到数列中min的后继提为根,把根的左孩子丢(shan)了就完成了(很容易YY到的对吧~)
#2.如何处理对当前数列中的数进行±k:
开个全局变量存整体的波动(?)值ff。那么删点的时候就把低于min-ff的删掉;又是仅对于当前的数,于是后来插入的数要-ff再插入,以此来保证新插入的数不受先前操作的影响。
p.s.输出的时候记得加上ff哦
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; #define maxn 101000 struct node { int d,c,n,f,son[2]; }tr[maxn*2];int len,root; int ls,num,zs;//ls-上面说的ff;num-员工人数(算上离开了的?);zs-离开的员工数(就是最后要输出的那个) void updata(int x) { int lc=tr[x].son[0],rc=tr[x].son[1]; tr[x].c=tr[lc].c+tr[rc].c+tr[x].n; } void add(int d,int f) { len++; tr[len].d=d;tr[len].f=f; tr[len].c=tr[len].n=1; tr[len].son[0]=tr[len].son[1]=0; if (d<tr[f].d) tr[f].son[0]=len;else tr[f].son[1]=len; } void rotate(int x) { int y=tr[x].f,z=tr[y].f,w,r,R; if (tr[y].son[0]==x) w=1;else w=0; r=tr[x].son[w];R=y; tr[R].son[1-w]=r; if (r!=0) tr[r].f=R; r=x;R=z; tr[R].son[(tr[R].son[0]==y)?0:1]=r; tr[r].f=R; r=y;R=x; tr[R].son[w]=r; tr[r].f=R; updata(y);updata(x); } void splay(int x,int rt) { while (tr[x].f!=rt) { int y=tr[x].f,z=tr[y].f; if (z==rt) rotate(x); else { if ((y==tr[z].son[0])==(x==tr[y].son[0])) rotate(y); else rotate(x);rotate(x); } }if (rt==0) root=x; } int findip(int d) { int x=root; while (tr[x].d!=d) { if (tr[x].d>d) { if (tr[x].son[0]!=0) x=tr[x].son[0];else break; }else if (tr[x].d<d) { if (tr[x].son[1]!=0) x=tr[x].son[1];else break; } }return x; } void ins(int d) { if (root==0) {add(d,0);root=len;return;}//每次都忘!!!!!!! int x=findip(d); if (tr[x].d==d) tr[x].n++; else add(d,x); updata(x); splay(x,0); } void del(int d) { int x=findip(d);splay(x,0); while (tr[x].d<d) { if (tr[x].son[1]!=0) { x=tr[x].son[1]; while (tr[x].son[0]!=0) x=tr[x].son[0]; }else {zs+=tr[x].c;root=len=0;return;} }splay(x,0); if (tr[x].son[0]!=0) zs+=tr[tr[x].son[0]].c; tr[x].son[0]=0; updata(x); } int findpm(int k) { int x=root; while (1) { int lc=tr[x].son[0],rc=tr[x].son[1]; if (tr[rc].c>=k) x=rc; else if (tr[rc].c+tr[x].n<k) {k-=tr[rc].c+tr[x].n;x=lc;} else break; }return tr[x].d; } int main() { //freopen("cashier.in","r",stdin); //freopen("cashier.out","w",stdout); int n,minn,i,x;char c; scanf("%d%d",&n,&minn); ls=zs=num=len=root=0; for (i=1;i<=n;i++) { scanf(" %c%d",&c,&x); if (c=='I') { if (x>=minn) {ins(x-ls);num++;} }else if (c=='A') ls+=x; else if (c=='S') { ls-=x; del(minn-ls); }else if (c=='F') { if (x>num-zs) printf("-1 "); else printf("%d ",findpm(x)+ls); } }printf("%d ",zs); return 0; }