N的范围很大,但Q的范围比较小.可以把TOP,QUERY操作用到的点分离出来,没用到的段缩成点
对于TOP 把x转到根,删除后加到开头位置
对于QUERY 旋转到根直接输出
对于RANK,递归
3 9 5 Top 1 Rank 3 Top 7 Rank 6 Rank 8 6 2 Top 4 Top 5 7 4 Top 5 Top 2 Query 1 Rank 6
Case 1: 3 5 8 Case 2: Case 3: 3 6
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=200200; char op[maxn][10]; int number[maxn]; int n; int s[maxn],e[maxn]; int p[maxn]; /***************SPLAY*********************/ int ch[maxn][2],num[maxn],sz[maxn],pre[maxn]; int tot1,root; void NewNode(int& x,int father,int k) { x=k; sz[x]=num[x]=e[x]-s[x]+1; ch[x][1]=ch[x][0]=0; pre[x]=father; } void Push_Up(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+num[x]; } void Build(int& x,int l,int r,int fa) { if(l>r) return ; int mid=(l+r)/2; NewNode(x,fa,mid); Build(ch[x][0],l,mid-1,x); Build(ch[x][1],mid+1,r,x); Push_Up(x); } void Init() { root=0; ch[root][0]=ch[root][1]=pre[root]=sz[root]=num[root]=0; Build(root,1,n,0); Push_Up(root); } void Rotate(int x,int kind) { int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; pre[y]=x; ch[x][kind]=y; Push_Up(y); } void Splay(int r,int goal) { while(pre[r]!=goal) { if(pre[pre[r]]==goal) { Rotate(r,ch[pre[r]][0]==r); } else { int y=pre[r]; int kind=(ch[pre[y]][0]==y); if(ch[y][kind]==r) Rotate(r,!kind); else Rotate(y,kind); Rotate(r,kind); } } Push_Up(r); if(goal==0) root=r; } int Get_Min(int r) { while(ch[r][0]) r=ch[r][0]; return r; } void Remove_Root() { if(ch[root][1]==0||ch[root][0]==0) { root=ch[root][1]+ch[root][0]; pre[root]=0; return ; } int k=Get_Min(ch[root][1]); Splay(k,root); ch[ch[root][1]][0]=ch[root][0]; root=ch[root][1]; pre[ch[root][0]]=root; pre[root]=0; Push_Up(root); } int Bin(int x) { int low=1,high=n,mid; while(low<=high) { mid=(low+high)/2; if(s[mid]<=x&&x<=e[mid]) return mid; if(s[mid]>x) high=mid-1; else low=mid+1; } return -1; } /************doit*********/ void TOP(int x) { int y=Bin(x); Splay(y,0); Remove_Root(); Splay(Get_Min(root),0); ch[y][0]=0; ch[y][1]=root; pre[root]=y;root=y; pre[root]=0; Push_Up(root); } int QUERY(int x) { int y=Bin(x); Splay(y,0); return sz[ch[root][0]]+1; } int RANK(int r,int x) { int t=sz[ch[r][0]]; if(x<=t) return RANK(ch[r][0],x); else if(x<=t+num[r]) { return s[r]+x-t-1; } else return RANK(ch[r][1],x-t-num[r]); } /*********DEBUG***********/ void showit(int x) { if(x) { showit(ch[x][0]); printf("结点: %2d 左儿子: %2d 右儿子: %2d 父结点: %2d size: %2d num: %2d \n", x,ch[x][0],ch[x][1],pre[x],sz[x],num[x]); showit(ch[x][1]); } } void debug() { cout<<"root : "<<root<<endl; showit(root); } int main() { int T_T,cas=1; scanf("%d",&T_T); while(T_T--) { printf("Case %d:\n",cas++); int t=0; int nn,mm; scanf("%d%d",&nn,&mm); for(int i=0;i<mm;i++) { scanf("%s%d",op[i],number+i); if(op[i][0]==‘T‘||op[i][0]==‘Q‘) { p[t++]=number[i]; } } n=0; p[t++]=1;p[t++]=nn; sort(p,p+t); t=unique(p,p+t)-p; for(int i=0;i<t;i++) { if(i!=0&&p[i]-1!=p[i-1]) { n++; s[n]=p[i-1]+1; e[n]=p[i]-1; } n++; s[n]=e[n]=p[i]; } Init(); for(int i=0;i<mm;i++) { if(op[i][0]==‘T‘) TOP(number[i]); else if(op[i][0]==‘Q‘) printf("%d\n",QUERY(number[i])); else printf("%d\n",RANK(root,number[i])); } } return 0; }
HDOJ 3436 Queue-jumpers,布布扣,bubuko.com
原文:http://blog.csdn.net/ck_boss/article/details/25229275