题目请戳这里
题目大意:有一个队,n个人,编号1-n,有3种操作:
top x:将编号x的人放到队列首;
query x:查询编号x的人现在排在第几位;
rank x:查询现在第x位的人编号;
题目分析:splay。人数编号是10^8级别的,但是操作不超过10^5个,只需将top操作中的编号离散化就可以了,因为剩下的人都是连续的,所以将剩下的连续的人缩成一个点,只记录起始位置的人和连续长度即可。
trick:n可以为1,这种情况下,任何操作都是无意义的,遇到查询操作就输出1。。这点TLE出翔了。。。
感想:splay非常强大,但是如果不能1y,那就意味着悲剧。。。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 200005; typedef __int64 ll; int hash[N]; int add[N]; int index[N]; int next[N]; struct spt { int l,r,f,val,size,len; }tree[N]; int n,m,q; struct node { char cmd; int x; }op[N]; void init() { for(int i = 0;i < N-10;i ++) next[i] = i + 1; } int newnode(int st,int ed) { int p = next[0]; next[0] = next[p]; tree[p].l = tree[p].r = tree[p].f = 0; tree[p].val = st; tree[p].size = tree[p].len = ed - st; return p; } void delnode(int p) { next[p] = next[0]; next[0] = p; } void del(int rt) { if(!rt) return; del(tree[rt].l); del(tree[rt].r); delnode(rt); } void pushup(int rt) { if(!rt) return; tree[rt].size = tree[tree[rt].l].size + tree[tree[rt].r].size + tree[rt].len; } void zig(int x) { int p = tree[x].f; tree[p].l = tree[x].r; if(tree[x].r) tree[tree[x].r].f = p; pushup(p); tree[x].r = p; tree[x].f = tree[p].f; pushup(x); tree[p].f = x; if(tree[x].f == 0) return; if(tree[tree[x].f].l == tree[x].r) tree[tree[x].f].l = x; else tree[tree[x].f].r = x; } void zag(int x) { int p = tree[x].f; tree[p].r = tree[x].l; if(tree[x].l) tree[tree[x].l].f = p; pushup(p); tree[x].l = p; tree[x].f = tree[p].f; pushup(x); tree[p].f = x; if(tree[x].f == 0) return; if(tree[tree[x].f].l == tree[x].l) tree[tree[x].f].l = x; else tree[tree[x].f].r = x; } int splay(int x,int goal) { while(tree[x].f != goal) { int p = tree[x].f; int g = tree[p].f; if(g == goal) { if(tree[p].l == x) zig(x); if(tree[p].r == x) zag(x); } else { if(tree[g].l == p && tree[p].l == x) zig(p),zig(x); else if(tree[g].l == p && tree[p].r == x) zag(x),zig(x); else if(tree[g].r == p && tree[p].l == x) zig(x),zag(x); else if(tree[g].r == p && tree[p].r == x) zag(p),zag(x); } } pushup(x); return x; } int build(int l,int r,int f) { if(l > r) return 0; int mid = (l + r)>>1; int p = newnode(hash[mid],hash[mid + 1]); tree[p].l = build(l,mid - 1,p); tree[p].f = f; tree[p].r = build(mid + 1,r,p); pushup(p); add[mid] = p; return p; } int getfront(int rt) { while(tree[rt].l) { rt = tree[rt].l; } return rt; } int getval(int pos,int rt) { if(!rt) return 0; if(pos <= tree[tree[rt].l].size) return getval(pos,tree[rt].l); if(pos <= tree[tree[rt].l].size + tree[rt].len) return rt;//pos - tree[tree[rt].l].size - 1 + tree[rt].val; return getval(pos - tree[tree[rt].l].size - tree[rt].len,tree[rt].r); } int Bin(int x) { int l,r,mid; l = 1;r = m; while(r >= l) { mid = (l + r)>>1; if(hash[mid] < x && hash[mid + 1] > x) return mid; if(hash[mid - 1] < x && hash[mid] > x) return mid - 1; if(hash[mid] == x) return mid; else if(hash[mid] > x) r = mid - 1; else l = mid + 1; } } void Top(int x,int &root) { int p = Bin(x); root = splay(add[p],0); if(tree[root].l == 0) { root = tree[root].r; tree[root].f = 0; } else if(tree[root].r == 0) { root = tree[root].l; tree[root].f = 0; } else {//后继旋到右子树,左子树挂到右子树,删除根 int nt = getfront(tree[root].r); tree[root].r = splay(nt,root); tree[tree[root].l].f = tree[root].r; tree[tree[root].r].l = tree[root].l; tree[tree[root].r].f = 0; root = tree[root].r; } pushup(root); int tmp = getfront(root); root = splay(tmp,0); tree[root].l = add[p]; tree[add[p]].f = root; tree[add[p]].l = tree[add[p]].r = 0; root = splay(add[p],0); } void Query(int x,int &root) { int p = Bin(x); root = splay(add[p],0); int ans = tree[tree[root].l].size + x - tree[root].val + 1; printf("%d\n",ans); } void Rank(int x,int &root) { int p = getval(x,root); root = splay(p,0); printf("%d\n",x - tree[tree[root].l].size - 1 + tree[root].val); } int main() { int _,i,j; int cas = 0; char ss[10]; int root; init(); scanf("%d",&_); while(_--) { scanf("%d%d",&n,&q); printf("n:%d q:%d\n",n,q); j = 1; printf("Case %d:\n",++cas); if(n == 1) { for(i = 1;i <= q;i ++) { scanf("%s%d",ss,&j); if(*ss == 'R' || *ss == 'Q') printf("1\n"); } continue; } for(i = 1;i <= q;i ++) { scanf("%s",ss); op[i].cmd = *ss; scanf("%d",&op[i].x); if(*ss == 'T') { hash[j] = op[i].x; j ++; } } sort(hash + 1,hash + j); m = 2; for(i = 2;i < j;i ++) if(hash[i] != hash[i - 1]) hash[m ++] = hash[i]; for(i = 2,j = m;i < j;i ++) if(hash[i] != hash[i - 1] + 1) hash[m ++] = hash[i - 1] + 1; if(hash[j - 1] < n) hash[m ++] = hash[j - 1] + 1; hash[m ++] = n + 1; if(hash[1] != 1) hash[m ++] = 1; sort(hash + 1,hash + m); m --; root = build(1,m - 1,0); for(i = 1;i <= q;i ++) { switch(op[i].cmd) { case 'T':Top(op[i].x,root);break; case 'Q':Query(op[i].x,root);break; case 'R':Rank(op[i].x,root);break; } } del(root); } return 0; } //140MS 4356K