题意:有n个人,编号分别为1~n,从小到大排成一列,有q次操作。 (n <= 10^8, q <= 10^5)
Top操作: 把编号为x的人拿出来放到最前面。
Query操作: 问编号为x的人现在在第几个。
Rank操作: 问第x个人编号为多少。
思路:把Top操作和Query操作的所有数离散化下,然后把n个人分成一个个区间,比如6个人,离散化编号4, 5的人,则分成区间(1, 3) (4, 4), (5, 5), (6, 6),保存好离散化的人在伸展树节点的下标,然后把区间建成伸展树就可以了。又被一个小细节坑了好久,调了好久,就是把节点放到最前面的时候我是先把它删除,然后在插入到最前面,可是我插入到最前面的时候忘了修改它的父亲导致debug好久才发现。。每个细节都不能出错才行啊。。
#include
#include
using namespace std;
typedef pair
pii;
#define lson x->ch[0]
#define rson x->ch[1]
#define ket (root->ch[1]->ch[0])
const int maxn = 100000+10;
struct NODE {
NODE *pre, *ch[2];
int l, r, sz, id;
void up() {
sz = ch[0]->sz + ch[1]->sz + r-l+1;
}
};
struct PP{
char s[6];
int x;
}a[maxn];
pii c[maxn<<1];
int M, b[maxn], pos[maxn];
struct Splaytree {
NODE node[maxn<<1], *null, *root;
int top;
void Rotate(NODE *x, int c) {
NODE *y = x->pre;
y->ch[!c] = x->ch[c];
if(x->ch[c] != null) x->ch[c]->pre = y;
x->pre = y->pre;
if(y->pre != null) y->pre->ch[y->pre->ch[1]==y] = x;
x->ch[c] = y; y->pre = x;
y->up();
}
void Splay(NODE *x, NODE *go) {
while(x->pre != go) {
if(x->pre->pre == go) Rotate(x, x->pre->ch[0] == x);
else {
NODE *y = x->pre, *z = y->pre;
int f = z->ch[1] == y;
if(y->ch[f] == x) Rotate(y, !f);
else Rotate(x, f);
Rotate(x, !f);
}
}
x->up();
if(go == null) root = x;
}
void RTO(int k, NODE *go) {
NODE *x = root;
while(lson->sz != k) {
if(lson->sz > k) x = lson;
else {
if(lson->sz + (x->r - x->l +1) -1 >= k) break;
k -= lson->sz + (x->r - x->l +1);
x = rson;
}
}
Splay(x, go);
}
NODE *newnode(int l, int r, NODE *f) {
NODE* x = &node[++top];
x->pre = f; x->id = top;
x->l = l; x->r = r; x->sz = r-l+1;
lson = rson = null;
return x;
}
void debug(NODE *x) {
if(x != null) {
printf("l = %d r = %d sz = %d lson = %d rson = %d\n", x->l, x->r, x->sz, lson->l, rson->l);
debug(lson);
debug(rson);
}
}
int bin(int val) {
int l = 0, r = M-1;
while(l <= r) {
int mid = (l+r)/2;
if(b[mid] == val) return mid;
if(b[mid] > val) r = mid-1;
else l = mid+1;
}
return -1;
}
NODE *build(int l, int r, NODE *f) {
if(l > r) return null;
int mid = (l+r)/2;
NODE *x = newnode(c[mid].first, c[mid].second, f);
if(c[mid].first == c[mid].second) {
int p = bin(c[mid].first);
if(p != -1) pos[p] = x->id;
}
lson = build(l, mid-1, x);
rson = build(mid+1, r, x);
x->up();
return x;
}
void init(int n) {
null = &node[0];
null->sz = null->l = null->r = null->id = 0;
top = 0;
root = newnode(-1, -1, null);
root->ch[1] = newnode(-1, -1, root);
ket = build(0, n-1, root->ch[1]);
root->ch[1]->up(); root->up();
}
int Query(int val) {
int p = bin(val);
NODE *x = &node[pos[p]];
Splay(x, null);
return root->ch[0]->sz;
}
int Rank(int val) {
NODE *x = root;
while(true) {
if(lson->sz == val) return x->l;
if(lson->sz > val) x = lson;
else {
if(lson->sz + x->r - x->l + 1 -1 >= val)
return val - lson->sz + x->l;
else {
val -= lson->sz + x->r - x->l + 1;
x = rson;
}
}
}
}
void Top(int val) {
int p = bin(val);
NODE *x = &node[pos[p]];
Splay(x, null);
int sum = lson->sz;
RTO(sum-1, null);
RTO(sum + x->r - x->l + 1, root);
x = ket; ket = null;
root->ch[1]->up(); root->up();
RTO(0, null);
RTO(1, root);
ket = x;
x->pre = root->ch[1];
root->ch[1]->up(); root->up();
Splay(x, null);
}
void solve() {
int n, q, t, cas = 1;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &q);
int tot = 0;
for(int i = 1;i <= q; i++) {
scanf("%s%d", a[i].s, &a[i].x);
if(a[i].s[0] != 'R') b[tot++] = a[i].x;
}
printf("Case %d:\n", cas++);
if(tot == 0) {
for(int i = 1;i <= q; i++) printf("%d\n", a[i].x);
continue;
}
sort(b, b + tot);
M = 1;
for(int i = 1;i < tot; i++) if(b[i] != b[i-1])
b[M++] = b[i];
tot = 0;
if(b[0] > 1) c[tot++] = pii(1, b[0]-1);
for(int i = 0;i < M; i++) {
c[tot++] = pii(b[i], b[i]);
if(i+1 == M) {
if(b[i] < n) c[tot++] = pii(b[i]+1, n);
}
else if(b[i]+1 < b[i+1])
c[tot++] = pii(b[i]+1, b[i+1]-1);
}
init(tot);
for(int i = 1;i <= q; i++) {
if(a[i].s[0] == 'T')
Top(a[i].x);
else if(a[i].s[0] == 'Q')
printf("%d\n", Query(a[i].x));
else
printf("%d\n", Rank(a[i].x));
}
}
}
}spt;
int main() {
spt.solve();
return 0;
}