http://acm.hdu.edu.cn/showproblem.php?pid=3436
离线操作,将两个数之间那段数的个数也当做一个节点放在伸展树中,找的时候根据节点的个数往左或往右找就好了
/*
关键是离散化的技巧
其他没什么
*/
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<algorithm>
using namespace std;
const int inf = ~0u>>2;
#define L ch[x][0]
#define R ch[x][1]
#define KT (ch[ ch[rt][1] ][0])
const int maxn = 200010;
struct SplayTree {
int sz[maxn];
int ch[maxn][2];
int pre[maxn];
int rt,top;
inline void up(int x){
sz[x] = s[x] + sz[ L ] + sz[ R ];
}
inline void Rotate(int x,int f){
int y=pre[x];
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
inline void Splay(int x,int goal){//将x旋转到goal的下面
while(pre[x] != goal){
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);
else {
int y=pre[x],z=pre[y];
int f = (ch[z][0]==y);
if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
up(x);
if(goal==0) rt=x;
}
inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
int x=rt;
while(sz[ L ] != k-1) {
if(k < sz[ L ]+1) x=L;
else {
k-=(sz[ L ]+1);
x = R;
}
}
Splay(x,goal);
}
inline void vist(int x){
if(x){
printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d sz=%d\n",x,L,R,mp[x],sz[x]);
vist(L);
vist(R);
}
}
void Del(){
int t=rt;
if(ch[rt][1]) {
rt=ch[rt][1];
RTO(1,0);
ch[rt][0]=ch[t][0];
if(ch[rt][0]) pre[ch[rt][0]]=rt;
}
else rt=ch[rt][0];
pre[rt]=0;
up(rt);
}
inline void Newnode(int &x,int id,int f){
x=++top;
L = R = 0;
pre[x] = f;
sz[x]=s[x]=ed[id]-bg[id]+1;
mp[x]=id;
node[id]=x;
}
void build(int &x,int l,int r,int f){
if(l>r) return ;
int m=l+r>>1;
Newnode(x,m,f);
build(L,l,m-1,x);
build(R,m+1,r,x);
pre[x]=f;
up(x);
}
void init(){
ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
rt=top=0;
scanf("%d%d",&n,&m);
tot=0;
int k=0;
num[k++]=1;
for(int i=1;i<=m;i++){
scanf("%s%d",op[i],&x[i]);
if(op[i][0]=='T' || op[i][0]=='Q') num[k++]=x[i];
}
num[k++]=n;
sort(num,num+k);
bg[tot]=num[0];
ed[tot++]=num[0];
for(int i=1;i<k;i++){
if(num[i]!=num[i-1]){
if(num[i-1]+1<num[i]) {
bg[tot]=num[i-1]+1;
ed[tot++]=num[i]-1;
}
bg[tot]=num[i];
ed[tot++]=num[i];
}
}
build(rt,0,tot-1,0);
}
void Insert(int &x,int id,int p){
if(x==0) {
Newnode(x,id,p);
Splay(x,0);
return ;
}
Insert(L,id,x);
up(x);
}
void Query(int xx){
int id=lower_bound(bg,bg+tot,xx)-bg;
Splay(node[id],0);;
printf("%d\n",sz[ch[rt][0]]+1);
}
void Top(int xx) {
int id=lower_bound(bg,bg+tot,xx)-bg;
Splay(node[id],0);
Del();
Insert(rt,id,0);
Splay(node[id],0);
}
int Find(int x,int xx){
int id=mp[x];
if(xx <= sz[ L ])
return Find(L,xx);
else if(xx <= sz[ L ] + s[x])
return bg[id] + (xx-sz[ L ]) -1;
else
return Find(R,xx - sz[ L ] - s[x]);
}
void solve() {
for(int i=1;i<=m;i++) {
if(op[i][0]=='T') {
Top(x[i]);
} else if(op[i][0]=='Q'){
Query(x[i]);
} else {
printf("%d\n",Find(rt,x[i]));
}
}
}
int bg[maxn];
int ed[maxn];
int num[maxn];
int s[maxn];
int mp[maxn];
int x[maxn];
int node[maxn];
int n,m,tot;
char op[maxn][6];
}spt;
int main(){
int t,ca=1;
scanf("%d",&t);
while(t--) {
printf("Case %d:\n",ca++);
spt.init();
spt.solve();
}
return 0;
}