【HDU 3436】Queue-jumpers(Splay)
2014-09-13 20:41
330 查看
Splay的基础操作。问题的关键就在于N非常大,就算是利用Splay数组也是远远开不下的,因此很自然地想到了hash一下
可以将所有要进行Top的节点和Query的节点
然后对于每一个节点或者每一个段,可以将它的长度表示出来(方便起见每个点可以看做一个长度为1的线段)
剩下的就是Splay的基础操作了
1、top:将节点删除后插入到队首
2、Rank:找到当前子树的第k个数
3、Query:询问第k个人的位置。可以将该点旋转至树根,那么左子树的个数+1就是其位置
下面是代码:
可以将所有要进行Top的节点和Query的节点
然后对于每一个节点或者每一个段,可以将它的长度表示出来(方便起见每个点可以看做一个长度为1的线段)
剩下的就是Splay的基础操作了
1、top:将节点删除后插入到队首
2、Rank:找到当前子树的第k个数
3、Query:询问第k个人的位置。可以将该点旋转至树根,那么左子树的个数+1就是其位置
下面是代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int SIZEN = 200025; int txt = 1; int has[SIZEN],cntx; int n_val[SIZEN]; int p[SIZEN>>1]; char op[SIZEN>>1]; int read(){ char ch = ' '; while(ch < '0' || ch > '9') ch = getchar(); int ans = 0; while(ch <= '9' && ch >='0'){ ans *= 10; ans += ch - '0'; ch = getchar(); } return ans; } struct SplayTree{ int ch[SIZEN][2]; int pre[SIZEN]; int sz[SIZEN]; int top,root; inline void pushup(int x){ sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + cnt[x]; } int Newnode(int x){ pre[x] = ch[x][0] = ch[x][1] = 0; cnt[x] = sz[x] = n_val[x + 1] - n_val[x]; return x; } void debug(){ printf("root:%d\n",root); Travel(root); } void Travel(int x){ if(ch[x][0]) Travel(ch[x][0]); printf("node:%d lson:%d rson:%d pre:%d sz:%d cnt:%d val:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],cnt[x],n_val[x]); if(ch[x][1]) Travel(ch[x][1]); } 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[y]) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x; ch[x][f] = y; pre[y] = x; pushup(y); } inline void Splay(int x,int 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); } } } pushup(x); if(goal == 0) root = x; } inline void build(int &x,int l,int r,int f){ if(l > r) return; int mid = (l + r) >> 1; x = Newnode(mid); build(ch[x][0],l,mid - 1,x); build(ch[x][1],mid + 1,r,x); pre[x] = f; pushup(x); } inline void init(){ ch[0][0] = ch[0][1] = pre[0] = 0; sz[0] = cnt[0] = 0; root = top = 0; } int findmax(int x){ while(ch[x][1]){ x = ch[x][1]; } return x; } int findmin(int x){ while(ch[x][0]){ x = ch[x][0]; } return x; } inline void del(int x){ Splay(x,0); if(ch[x][0] == 0){ root = ch[x][1]; ch[x][0] = ch[x][1] = pre[x] = 0; pre[root] = 0; return; } int m = findmax(ch[root][0]); Splay(m,root); ch[m][1] = ch[x][1]; ch[x][0] = ch[x][1] = 0; pre[x] = 0; pre[ ch[m][1] ] = m; root = m; pre[root] = 0; pushup(root); } inline void query(int i){ int loc = p[i]; loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1; Splay(loc,0); printf("%d\n",sz[ ch[root][0] ] + 1); } inline void Top(int i){ int loc = p[i]; loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1; del(loc); if(root == 0){ root = loc; ch[root][0] = ch[root][1] = 0; pre[root] = 0; return; } int Min = findmin(root); Splay(Min,0); ch[root][0] = loc; pre[loc] = root; ch[loc][0] = ch[loc][1] = 0; pushup(loc); pushup(root); Splay(loc,0); } inline int getrank(int x,int k){ int t = sz[ ch[x][0] ]; if(t >= k) return getrank(ch[x][0],k); else if(k <= t + cnt[x]) return n_val[x] + k - t - 1; else return getrank(ch[x][1],k - t - cnt[x]); } inline void rank(int i){ int k = p[i],loc; printf("%d\n",getrank(root,k)); } int cnt[SIZEN]; }; SplayTree spt; void Has(int &cnt,int n){ has[cnt++] = n + 1;has[cnt++] = 1; has[cnt++] = 0; sort(has,has+cnt); int ncnt = 0; n_val[ncnt++] = has[0]; for(int i=1;i<cnt;i++){ if(has[i] != has[i - 1]){ if(has[i - 1] + 1 != has[i]) n_val[ncnt++] = has[i - 1] + 1; n_val[ncnt++] = has[i]; } } cnt = ncnt; } void solve(){ int n,q; char t_op[10]; scanf("%d%d",&n,&q); printf("Case %d:\n",txt++); spt.init(); cntx = 0; has[cntx++] = 0; for(int i=0;i<q;i++){ scanf("%s",t_op); p[i] = read(); op[i] = t_op[0]; if(op[i] != 'R') has[cntx++] = p[i]; } Has(cntx,n); spt.build(spt.root,1,cntx - 2,0); spt.pushup(spt.root); for(int i=0;i<q;i++){ if(op[i] == 'T') spt.Top(i); else if(op[i] == 'R') spt.rank(i); else if(op[i] == 'Q') spt.query(i); } } int main() { //freopen("data.in","r",stdin); int _; scanf("%d",&_); while(_--) solve(); }
相关文章推荐
- HDU 3436--Queue-jumpers (树状数组 or Splay Tree)
- hdu 3436 Queue-jumpers(Splay)
- HDU 3436 Queue-jumpers(SplayTree+离散化)
- HDU 3436 Queue-jumpers(Splay)
- Splay树 + 离散化 —— HDU 3436 Queue-jumpers
- HDU-3436 Queue-jumpers(Splay树)
- hdu 3436 Queue-jumpers(splay)
- HDU 3436 Queue-jumpers
- hdu 3436 Queue-jumpers
- hdu 3436 Queue-jumpers (经典离散化,树状数组实现lower_bound)
- HDU 3436 Queue-jumpers
- hdu-3436-Queue-jumpers-伸展树
- hdu 3436 Queue-jumpers(Splay Tree)
- HDU 3436 Queue-jumpers (Splay tree)
- Hdu 3436 Queue-jumpers(把第x个人放到队伍的前面,查询第x个人的位置,查询第x个位置是哪个人)
- HDU 3436 Queue-jumpers (Splaytree)
- HDU 3436 Queue-jumpers
- HDU 3436 Queue-jumpers(splay tree)
- HDU 3436 Queue-jumpers
- HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动