题意:
Ponyo and Garfield are waiting outside the box-office for theirfavorite movie. Because queuing is so boring, that they want to play a game tokill the time. The game is called “Queue-jumpers”. Suppose that there are Npeople numbered from 1 to N stand in a line initially. Each time you should simulateone of the following operations:
1. Top x:Take person x to the front of the queue
2. Queryx: calculate the current position of person x
3. Rankx: calculate the current person at position x
Where x is in [1,N].
Ponyo is so cleverthat she plays the game very well while Garfield has no idea. Garfield is nowturning to you for help.
题解:
伸展树的应用:
对于操作1:现将x旋转到根节点,删除根,用右边最小的节点当根,然后把右边最小的旋转到根,此时根左边已经没有节点。然后将x节点作为根节点,右节点指向刚才那个根,左节点为0,即完成插入首部。
对于操作2:找排名。
对于操作3:左右找呗!
N过大,对TOP命令进行区间离散化。
#include<bits/stdc++.h>using namespace std;const int maxn = 2e5+99;int n,q,t;
int s[maxn],e[maxn],cnt;int p[maxn];
char op[maxn][10];
int qnum[maxn];int bin(int x)
{int l=1-1,r=cnt+1;while(r>l+1){int m = (l+r)>>1;if(s[m] <= x && x<= e[m])return m;else if(x<s[m])r=m;else l = m;}return -1;
}int sz[maxn],num[maxn],pre[maxn],ch[maxn][2],root;void pushup(int r)
{sz[r] = sz[ch[r][0]]+sz[ch[r][1]]+num[r];
}void rotate(int x,int d)
{int y = pre[x];ch[y][!d] = ch[x][d];pre[ch[x][d]] = y;if(pre[y])ch[pre[y]][ch[pre[y]][1]==y] = x;pre[x] = pre[y];ch[x][d] = y;pre[y] = x;pushup(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 d = ch[pre[y]][0] == y;if(ch[y][d] == r){rotate(r,!d);rotate(r,d);}else{rotate(y,d);rotate(r,d);}}}pushup(r);if(goal==0)root = r;
}void newnode(int &r,int fa,int k)
{r = k;num[r] = sz[r] = e[k] - s[k] + 1;pre[r] = fa;ch[r][0] = ch[r][1] = 0;
}void build(int &x,int l,int r,int fa)
{if(l>r)return;int m = (l+r)>>1;newnode(x,fa,m);build(ch[x][0],l,m-1,x);build(ch[x][1],m+1,r,x);pushup(x);
}void init()
{root = 0;pre[root] = ch[root][0] = ch[root][1] = sz[root] = num[root] = 0;build(root,1,cnt,0);
}int getmin(int r)
{while(ch[r][0]){r = ch[r][0];}return r;
}void ddelete()
{if(ch[root][0]==0 || ch[root][1]==0){root = ch[root][0] + ch[root][1];pre[root] = 0;return;}int k = getmin(ch[root][1]);splay(k,root);ch[k][0] = ch[root][0];pre[ch[root][0]]=k;root = k;pre[k] = 0;pushup(root);//不用加也可
}void top(int x)
{int r = bin(x);splay(r,0);ddelete();splay(getmin(root),0);ch[r][0] = 0;ch[r][1] = root;pre[r] = 0;pre[root] = r;root = r;pushup(r);
}int query(int x)
{int r = bin(x);splay(r,0);return sz[ch[r][0]]+x-s[r]+1;
}int getrank(int r,int k)
{int t = sz[ch[r][0]];if(k<=t)return getrank(ch[r][0],k);else if(k<=t+num[r])return s[r]+k-t-1;else return getrank(ch[r][1],k-t-num[r]);
}int main()
{scanf("%d",&t);for(int kase = 1;kase<=t;kase++){scanf("%d%d",&n,&q);int t = 0;for(int i=1;i<=q;i++){scanf("%s%d",op[i],qnum+i);if(op[i][0] == 'T'){p[t++] = qnum[i];}}p[t++] = 1;p[t++] = n;sort(p,p+t);t = unique(p,p+t)-p;cnt = 0;for(int i = 0;i<t;i++){if(i>0 && p[i]>p[i-1]+1){cnt++;s[cnt] = p[i-1]+1;e[cnt] = p[i] - 1;}cnt++;s[cnt] = e[cnt] = p[i];}init();printf("Case %d:\n",kase);for(int i=1;i<=q;i++){if(op[i][0] == 'T')top(qnum[i]);else if(op[i][0]=='Q')printf("%d\n",query(qnum[i]) );else if(op[i][0]=='R')printf("%d\n",getrank(root,qnum[i]));}}
}