从一开始学离散化就对它没有半毛钱好感,感觉出这种题纯属恶心人。
可以将Top x全部取出来然后离散化,缩点。剩下的就是伸展了,不再赘述。
也有人拿线段树过,一直没有想明白. . .
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 9999991
using namespace std;
const int MAXN = 200100;
struct N
{
//info
int son[2],pre;
//data
int data;
int sum;
int ls,rs,s;
}st[200100];
struct O
{
int ty;
int x;
}com[101000];
struct NNum
{
int num,w,site;
}Num[201000],TNum[201000];
int Top_Num;
int Top;
void Updata(int root)
{
st[root].ls = 0,st[root].rs = 0;
if(st[root].son[0] != -1)
st[root].ls = st[st[root].son[0]].s;
if(st[root].son[1] != -1)
st[root].rs = st[st[root].son[1]].s;
st[root].s = st[root].rs + st[root].ls + st[root].sum;
}
void Push_Down(int root)
{
;
}
void Init(int &root,int s,int e,int pre)
{
if(s > e)
return ;
int mid = (s+e)>>1;
root = Top++;
st[root].data = Num[mid].num;
st[root].sum = Num[mid].w;
Num[mid].site = root;
st[root].pre = pre;
st[root].son[0] = -1,st[root].son[1] = -1;
Init(st[root].son[0],s,mid-1,root);
Init(st[root].son[1],mid+1,e,root);
Updata(root);
}
void Rotate(int root,int dir)
{
st[st[root].pre].son[dir] = st[root].son[1^dir];
st[root].son[1^dir] = st[root].pre;
if(st[st[st[root].pre].pre].son[0] == st[root].pre)
st[st[st[root].pre].pre].son[0] = root;
else
st[st[st[root].pre].pre].son[1] = root;
int temp = st[root].pre;
st[root].pre = st[st[root].pre].pre;
st[temp].pre = root;
if(st[temp].son[dir] != -1)
st[st[temp].son[dir]].pre = temp;
Updata(temp);
Updata(root);
}
int Splay(int root,int goal)
{
while(st[root].pre != goal)
{
Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1));
}
return root;
}
int Search_Site(int root,int site)
{
//Push_Down(root);
int temp;
if(site <= st[root].ls || st[root].ls + st[root].sum < site)
{
if(st[root].ls + st[root].sum < site)
temp = Search_Site(st[root].son[1],site - st[root].ls - st[root].sum);
else
temp = Search_Site(st[root].son[0],site);
}
else
{
temp = root;
}
//Updata(root);
return temp;
}
bool cmp(NNum n1 , NNum n2)
{
return n1.num < n2.num;
}
int Del_Same(int n,NNum *TNum,NNum *Num)
{
sort(Num+1,Num+Top_Num,cmp);
int i,j;
TNum[1].num = Num[1].num;
TNum[1].w = 1;
for(i = 2,j = 1; i < n; ++i)
{
if(Num[i].num != TNum[j].num)
{
if(Num[i].num > TNum[j].num+1)
{
TNum[j+1].num = TNum[j].num+1;
TNum[j+1].w = Num[i].num-TNum[j].num-1;
++j;
}
TNum[++j].num = Num[i].num;
TNum[j].w = 1;
}
}
return j;
}
void Link(int &root,int tr,int dir,int pre)
{
if(root == -1)
{
root = tr;
st[tr].pre = pre;
}
else
{
Link(st[root].son[dir],tr,dir,root);
}
Updata(root);
}
int bs(int s,int e,int x)
{
int mid = (s+e)>>1;
while(s < e)
{
if(Num[mid].num <= x && x < Num[mid].num + Num[mid].w)
return Num[mid].site;
if(x < Num[mid].num)
e = mid-1;
else
s = mid+1;
mid = (s+e)>>1;
}
return Num[s].site;
}
void Op_Top(int x,int &R)
{
R = Splay(bs(1,Top_Num,x),0);
int TR = R;
int tr = st[R].son[1];
R = st[R].son[0];
st[0].son[0] = R;
st[R].pre = 0;
st[TR].son[0] = -1,st[TR].son[1] = -1;
st[TR].ls = 0,st[TR].rs = 0;
st[TR].s = st[TR].sum;
Link(R,tr,1,0);
R = Splay(Search_Site(R,2),0);
R = Splay(Search_Site(R,1),0);
st[st[R].son[1]].son[0] = TR;
st[TR].pre = st[R].son[1];
Updata(st[R].son[1]);
Updata(R);
}
int Query(int x,int &R)
{
R = Splay(bs(1,Top_Num,x),0);
return st[R].ls-st[R].data+x;
}
int Rank(int x,int &R)
{
R = Splay(Search_Site(R,x),0);
return st[R].data+(x-st[R].ls-1);
}
int Judge(char order)
{
if(order == 'T')
return 1;
if(order == 'Q')
return 2;
if(order == 'R')
return 3;
}
int main()
{
int T,icase = 1;
int i,n,m;
int root;
char order[10];
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
Top_Num = 1;
for(i = 1; i <= m; ++i)
{
scanf("%s %d",order,&com[i].x);
if(order[0] == 'T')
TNum[Top_Num++].num = com[i].x;
com[i].ty = Judge(order[0]);
}
TNum[Top_Num++].num = 0;
TNum[Top_Num++].num = n+1;
Top_Num = Del_Same(Top_Num,Num,TNum);
root = -1,Top = 1;
Init(root,1,Top_Num,0);
st[0].son[0] = root,st[0].son[1] = -1;
st[root].pre = 0;
printf("Case %d:\n",icase++);
for(i = 1; i <= m; ++i)
{
if(com[i].ty == 1)
{
Op_Top(com[i].x,root);
}
else if(com[i].ty == 2)
{
printf("%d\n",Query(com[i].x,root));
}
else
{
printf("%d\n",Rank(com[i].x+1,root));
}
}
}
return 0;
}