bzoj1503 [NOI2004]郁闷的出纳员——splay
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1503
虽然是平衡树裸题,但一直TLE,只好改了insert和move的写法...
本来想着每次降工资就把工资-det加进去,转到根节点,然后把小于它的都删掉,再把它也删掉这样...
而且连insert都会TLE...是因为需要每次把新加入的点旋转到根...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=100005; int n,mn,det,val[maxn],siz[maxn],num[maxn],c[maxn][3],fa[maxn],nd=1,rt,lv; //void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+num[x];} void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;} //void insert(int x,int v) //{ // if(!rt){rt=1;val[1]=v;num[1]=1;siz[1]=1;return;} //// if(val[x]==v){num[x]++;siz[x]++;pushup(fa[x]);} // if(val[x]>v) // { // if(c[x][0])insert(c[x][0],v); // else c[x][0]=++nd,val[nd]=v,num[nd]=1,siz[nd]=1,fa[nd]=x; // pushup(x);return; // } //// if(val[x]<v) // else // { // if(c[x][1])insert(c[x][1],v); // else c[x][1]=++nd,val[nd]=v,num[nd]=1,siz[nd]=1,fa[nd]=x; // pushup(x);return; // } //} int find(int x,int v) { if(val[x]==v)return x; return find(c[x][val[x]<v],v); } void rotate(int x,int &k) { int y=fa[x],z=fa[y],d=(c[y][1]==x); if(y==k)k=x; else c[z][c[z][1]==y]=x; fa[x]=z; fa[y]=x; fa[c[x][d^1]]=y; c[y][d]=c[x][d^1]; c[x][d^1]=y; pushup(y);pushup(x); } void splay(int x,int &k) { while(x!=k) { int y=fa[x],z=fa[y]; if(y!=k) { if((c[y][0]==x)^(c[z][0]==y))rotate(x,k); else rotate(y,k); } rotate(x,k); } } void Insert(int &k,int x,int Last) { if(!k) { k=++nd;fa[k]=Last;siz[k]=1; val[k]=x;splay(k,rt);// return; } if(x<val[k]) Insert(c[k][0],x,k); else Insert(c[k][1],x,k); } //void move() //{ // insert(rt,mn-det);int x=find(rt,mn-det); // splay(x,rt);lv+=siz[c[rt][0]]; // if(num[rt]==1) // { // splay(c[rt][1],rt); // int y=c[rt][0];c[rt][0]=0;fa[y]=0;siz[y]=0; // } // else {num[rt]--;siz[rt]--;} // pushup(rt); //} int move(int &k,int Last) { if(!k) return 0; int rtn=0; if(val[k]+det<mn) { rtn=move(c[k][1],k)+siz[c[k][0]]+1; siz[c[k][1]]=siz[k]-rtn; k=c[k][1],fa[k]=Last; } else { rtn=move(c[k][0],k); siz[k]-=rtn; } return rtn; } int query(int x,int k) { if(siz[c[x][0]]+1==k)return val[x]; if(siz[c[x][0]]+1>k)return query(c[x][0],k); else return query(c[x][1],k-siz[c[x][0]]-1); } int main() { scanf("%d%d",&n,&mn); char ch[3]; for(int i=1,x;i<=n;i++) { scanf("%s%d",&ch,&x); if(ch[0]=='I') { // if(x<mn)lv++; // if(x>=mn)insert(rt,x-det); if(x>=mn)Insert(rt,x-det,0); } if(ch[0]=='A')det+=x; // if(ch[0]=='S')det-=x,move(); if(ch[0]=='S')det-=x,lv+=move(rt,0); if(ch[0]=='F') { if(x>siz[rt])printf("-1\n"); else printf("%d\n",query(rt,siz[rt]-x+1)+det); } } printf("%d",lv); return 0; }