Queue-jumpers - 平衡樹

題面

Ponyo and Garfield are waiting outside the box-office for their favorite movie. Because queuing is so boring, that they want to play a game to kill the time. The game is called “Queue-jumpers”. Suppose that there are N people numbered from 1 to N stand in a line initially. Each time you should simulate one of the following operations: 
1.  Top x :Take person x to the front of the queue 
2.  Query x: calculate the current position of person x 
3.  Rank x: calculate the current person at position x 
Where x is in [1, N]. 
Ponyo is so clever that she plays the game very well while Garfield has no idea. Garfield is now turning to you for help. 

Input

In the first line there is an integer T, indicates the number of test cases.(T<=50) 
In each case, the first line contains two integers N(1<=N<=10^8), Q(1<=Q<=10^5). Then there are Q lines, each line contain an operation as said above. 

Output

For each test case, output “Case d:“ at first line where d is the case number counted from one, then for each “Query x” operation ,output the current position of person x at a line, for each “Rank x” operation, output the current person at position x at a line.

題解

這道題標籤是平衡樹,所以要用平衡樹做。

這道題的N很大,但Q很小,但是又有數字又有序號導致我們不好用離散化。

回想一下線段樹,當我們想用離散又不能用的時候,我們就會用動態開點。

這道題也是一個道理,我們一開始用一個大點存1~N,以後每個小點都存一個子區間,

再用另一棵樹存出現過的數字,每次找前綴,再通過這個前綴找到包含它的子區間的第一棵樹上的節點編號。

CODE

本人代碼有點醜,請見諒。

(別複製了,我特地把一個地方改成錯的了)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL long long
#define MAXN 200000 + 5
using namespace std;
inline LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
	return x * f;
}
LL n,m,i,j,s,o,k,cnt,root,root2;
struct tr{
	int s[2];
	LL key;
	int heap,siz,cntp,nml,nmr;
	tr(){key = 0;s[0] = s[1] = 0;heap = 0;siz = 0;cntp = 0;nml = 0;nmr = 0;}
}tre[MAXN];
int maketre(LL ky,int hp,int numl,int numr) {
	tre[++cnt] = tr();
	tre[cnt].key = ky;
	tre[cnt].heap = hp;
	tre[cnt].s[0] = tre[cnt].s[1] = 0;
	tre[cnt].siz = tre[cnt].cntp = numr - numl + 1;
	tre[cnt].nml = numl;
	tre[cnt].nmr = numr;
	return cnt;
}
void update(int x) {
	tre[x].siz = tre[tre[x].s[0]].siz + tre[tre[x].s[1]].siz + tre[x].cntp;
	return ;
}
int splay(int x,int d) {
	int ad = tre[x].s[d];
	tre[x].s[d] = tre[ad].s[d^1];
	tre[ad].s[d^1] = x;
	update(x);
	update(ad);
	return ad;
}
int ins(int x,LL tk,int numl,int numr) {
	if(x == 0) return maketre(tk,unsigned(rand()) + 1,numl,numr);
	if(tre[x].key == tk) {
		tre[x].cntp ++;
		update(x);
		return x;
	}
	int d = tk > tre[x].key;
	tre[x].s[d] = ins(tre[x].s[d],tk,numl,numr);
	if(tre[tre[x].s[d]].heap < tre[x].heap) return splay(x,d);
	update(x);
	return x;
}
int del(int x,LL ky) {
	if(x == 0) return 0;
	if(tre[x].key == ky) {
		if(tre[x].cntp > 1) {
			tre[x].cntp --;
			update(x);
			return x;
		}
		else {
			if(tre[x].s[0] && tre[x].s[1]) {
				int d = tre[tre[x].s[1]].heap < tre[tre[x].s[0]].heap;
				int rep = splay(x,d);
				tre[rep].s[d^1] = del(x,ky);
				update(rep);
				return rep;
			}
			if(tre[x].s[0]) return tre[x].s[0];
			return tre[x].s[1];
		}
	}
	else {
		int d = ky > tre[x].key;
		tre[x].s[d] = del(tre[x].s[d],ky);
		update(x);
		return x;
	}
}
int idp(int x,LL m) {
	if(x == 0) return 0;
	if(tre[tre[x].s[0]].siz < m && tre[tre[x].s[0]].siz + tre[x].cntp >= m) {
		return x;
	}
	if(tre[tre[x].s[0]].siz >= m) {
		return idp(tre[x].s[0],m);
	}
	return idp(tre[x].s[1],m - tre[tre[x].s[0]].siz - tre[x].cntp);
}
int pa(int x,LL m) {
	int ren;
	if(x == 0) ren = 1;
	else if(tre[x].key == m) {
		ren = tre[tre[x].s[0]].siz + 1;
	}
	else if(tre[x].key > m) {
		ren = pa(tre[x].s[0],m);
	}
	else ren = pa(tre[x].s[1],m) + tre[tre[x].s[0]].siz + tre[x].cntp;
	return ren;
}
int pre(int root,LL m) {
	int rep = pa(root,m);
	return idp(root,rep - 1);
}
int nex(int root,LL m) {
	int rep = pa(root,m);
	int repd = idp(root,rep);
	if(tre[repd].key == m) return idp(root,rep + tre[repd].cntp);
	return idp(root,rep);
}
int main() {
	int T = read(),cn = 0;
	while(T --) {
		printf("Case %d:\n",++cn);
		cnt = root = root2 = 0;
		n = read();m = read();
		root = ins(root,1,1,n);
		root2 = ins(root2,1,cnt,cnt);
		char ss[20];
		for(int i = 1;i <= m;i ++) {
			scanf("%s",ss + 1);s = read();
			if(ss[1] == 'T') {
				int d = pre(root2,s + 1);
				d = tre[d].nml;
				int l = tre[d].nml,r = tre[d].nmr,ky = tre[d].key;
				root = del(root,ky);
				root2 = del(root2,l);
				if(l < s) {
					root = ins(root,ky,l,s - 1);
					root2 = ins(root2,l,cnt,cnt);
				}
				if(r > s) {
					root = ins(root,ky + (s+1 - l),s + 1,r);
					root2 = ins(root2,s + 1,cnt,cnt);
				}
				d = idp(root,1);
				root = ins(root,tre[d].key - 1,s,s);
				root2 = ins(root2,s,cnt,cnt);
			}
			else if(ss[1] == 'Q') {
				int d = pre(root2,s + 1);
				d = tre[d].nml;
				int l = tre[d].nml,r = tre[d].nmr,ky = tre[d].key;
				printf("%d\n",pa(root,ky) + s - l);
			}
			else if(ss[1] == 'R') {
				int d = idp(root,s);
				int p = pa(root,tre[d].key);
				printf("%d\n",tre[d].nml + s - p);
			}
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章