zoukankan      html  css  js  c++  java
  • HDU 3436 Queue-jumpers Splay

    这题用Splay写得我蛋疼菊紧,4000b的代码还有debug半天,看来我的splay姿势还不够好a = =

    首先N是很大的,所以离散化是必然的,把要Top操作的和要Query操作的编号单独划分为一个区间,然后再中间会产生其他的区间,把这些区间缩点,然后离散化就好了。

    三个操作其实不难实现,Top操作只要先把这个节点删除,然后把节点的其他值不变,key值变成一个极小值再重新插入就好,可以把极小值直接设成0,因为据说splay是稳定的,不过保险起见我还是设置了一个tpos变量维护了一下当前的极小值,还是比较方便的。

    Rank操作其实就是一个找第k大,不同的就是这里节点本身的大小有可能不是1,要稍微处理一下。

    Query操作就是找有几个节点比指定节点小,直接把这个节点splay到根,然后取左子树大小用即可。一开始我写成先找到这个节点,然后沿着父节点一路往上加的SB做法,直接TLE了两发,没有利用好splay的性质a,多伸展几下树也会平衡一点o(╯□╰)o

    至于如何快速找到person,只要维护一个数组指向节点的编号就好。

    不过感觉这题用线段树很好写a,只要在前面留Q个空位就好了。 。。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 3e5 + 10;
    int ch[maxn][2], fa[maxn], rsize[maxn], size[maxn], key[maxn], nstr[maxn], chcnt, root;
    int n, q, vnum[maxn], vcnt, qval[maxn], tpos, pos[maxn], pid[maxn];
    int node_size[maxn], node_str[maxn], node_cnt;
    char cmd[maxn][16];
    
    inline void pushup(int x) {
    	size[x] = rsize[x];
    	for (int i = 0; i < 2; i++) if (ch[x][i]) {
    		size[x] += size[ch[x][i]];
    	}
    }
    
    int getID(int v) {
    	return lower_bound(vnum, vnum + vcnt, v) - vnum;
    }
    
    void build_node() {
    	//缩点
    	for (int i = 1; i < vcnt; i++) {
    		int tmp = vnum[i] - vnum[i - 1] - 1;
    		if (tmp) {
    			node_size[++node_cnt] = tmp;
    			node_str[node_cnt] = vnum[i - 1] + 1;
    		}
    		node_size[++node_cnt] = 1;
    		node_str[node_cnt] = vnum[i];
    		pid[i] = node_cnt;
    	}
    	if (vnum[vcnt - 1] < n) {
    		node_size[++node_cnt] = n - vnum[vcnt - 1];
    		node_str[node_cnt] = vnum[vcnt - 1] + 1;
    	}
    }
    
    int newNode(int &r, int father, int v, int rz, int ns) {
    	r = ++chcnt;
    	ch[r][0] = ch[r][1] = 0;
    	rsize[r] = rz;
    	key[r] = v;
    	fa[r] = father;
    	nstr[r] = ns;
    	return r;
    }
    
    void build_tree(int l, int r, int &rt, int father) {
    	int mid = l + r >> 1;
    	rt = pos[mid] = newNode(rt, father, mid, node_size[mid], node_str[mid]);
    	if (l < mid) build_tree(l, mid - 1, ch[rt][0], rt);
    	if (r > mid) build_tree(mid + 1, r, ch[rt][1], rt);
    	pushup(rt);
    }
    
    inline void rotate(int x, int d) {
    	int y = fa[x];
    	ch[y][d ^ 1] = ch[x][d];
    	fa[ch[x][d]] = y;
    	if (fa[y]) ch[fa[y]][y == ch[fa[y]][1]] = x;
    	fa[x] = fa[y];
    	ch[x][d] = y;
    	fa[y] = x;
    	pushup(x);
    	pushup(y);
    }
    
    inline void splay(int x, int goal) {
    	while (fa[x] != goal) {
    		int y = fa[x], d = (x == ch[y][1]);
    		if (fa[y] == goal) rotate(x, d ^ 1);
    		else {
    			int z = fa[y], d1 = (y == ch[z][1]);
    			if (d == d1) {
    				rotate(y, d ^ 1); rotate(x, d ^ 1);
    			}
    			else {
    				rotate(x, d ^ 1); rotate(x, d1 ^ 1);
    			}
    		}
    	}
    	pushup(x);
    	if (goal == 0) root = x;
    }
    
    inline int findMax(int rt) {
    	while (ch[rt][1]) rt = ch[rt][1];
    	return rt;
    }
    
    inline void remove(int x) {
    	splay(x, 0);
    	int lc = ch[x][0], rc = ch[x][1];
    	if (lc) {
    		int u = findMax(lc);
    		splay(u, x);
    		fa[u] = 0;
    		if(rc) fa[rc] = u;
    		ch[u][1] = rc;
    		root = u;
    		pushup(u);
    	}
    	else if(rc) {
    		fa[rc] = 0;
    		root = rc;
    		pushup(rc);
    	}
    	else root = 0;
    }
    
    inline int insert(int v, int rz, int ns) {
    	int u = root;
    	if (root == 0) {
    		newNode(root, 0, v, rz, ns);
    		return root;
    	}
    	while (ch[u][v > key[u]]) u = ch[u][v > key[u]];
    	int r = newNode(ch[u][v > key[u]], u, v, rz, ns);
    	splay(r, 0);
    	return r;
    }
    
    inline void setTop(int x) {
    	x = pid[getID(x)];
    	remove(pos[x]);
    	pos[x] = insert(--tpos, node_size[x], node_str[x]);
    }
    
    inline int query(int x) {
    	x = pos[pid[getID(x)]];
    	splay(x, 0);
    	return size[ch[x][0]] + 1;
    }
    
    inline int findkth(int rt, int k) {
    	int lsize = size[ch[rt][0]];
    	if (lsize >= k) return findkth(ch[rt][0], k);
    	else if (lsize + rsize[rt] >= k) return nstr[rt] + k - lsize - 1;
    	else return findkth(ch[rt][1], k - lsize - rsize[rt]);
    }
    
    int main() {
    	int T; scanf("%d", &T);
    	for (int kase = 1; kase <= T; kase++) {
    		printf("Case %d:
    ", kase);
    		scanf("%d%d", &n, &q);
    		//加入把要进行Top,和Query操作的值离散化
    		vcnt = node_cnt = tpos = 0;
    		vnum[vcnt++] = 0;
    		chcnt = 0;
    		for (int i = 1; i <= q; i++) {
    			scanf("%s%d", cmd[i], &qval[i]);
    			if (cmd[i][0] == 'T' || cmd[i][0] == 'Q') {
    				vnum[vcnt++] = qval[i];
    			}
    		}
    		sort(vnum, vnum + vcnt);
    		vcnt = unique(vnum, vnum + vcnt) - vnum;
    		build_node();
    		build_tree(1, node_cnt, root, 0);
    		for (int i = 1; i <= q; i++) {
    			if (cmd[i][0] == 'T') setTop(qval[i]);
    			else if (cmd[i][0] == 'R') printf("%d
    ", findkth(root, qval[i]));
    			else printf("%d
    ", query(qval[i]));
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    软件体系架构复习要点
    Operating System on Raspberry Pi 3b
    2019-2020 ICPC North-Western Russia Regional Contest
    2019 ICPC ShenYang Regional Online Contest
    2019 ICPC XuZhou Regional Online Contest
    2019 ICPC NanChang Regional Online Contest
    2019 ICPC NanJing Regional Online Contest
    Codeforces Edu Round 72 (Rated for Div. 2)
    Codeforces Round #583 (Div.1+Div.2)
    AtCoder Beginning Contest 139
  • 原文地址:https://www.cnblogs.com/rolight/p/4278980.html
Copyright © 2011-2022 走看看