#207-[伸展树]买票

Description

排队买票是一件令人很焦躁的事情。售票窗口前排了一列长队,而且不断有人往前插队。由于天太黑了,人们并不知道有人插队。但是每个人身上有一个标记(不同人的标记可能相同)Vi,并且知道第i个人来了队伍之后会走到第Pi个人的后面。售票窗口记为第0个人,所以走到第0个人的后面意味着插到队伍首端了。

现在,给出以上信息,你能求出最后的V的序列吗?

Input

输入数据第一行包含一个整数n(1<=n<=200000),代表总人数。

接下来第n行,每行两个整数Pi和Vi,其中0<=Pi<=i-1,0<=Vi<=32767。

Output

输出一行共n个整数,代表最后的V的序列。

4
0 20523
1 19243
1 3890
0 31492
  • Sample Input

31492 20523 3890 19243
  • Sample Output

  • 一句话:链表太慢!考虑Splay插入。

  • #include 
    #include 
    
    using namespace std;
    const int MAXN = 200010;
    
    int fa[MAXN], ch[MAXN][2], key[MAXN], tsize[MAXN], id = 0, root = 0;
    
    int newnode(int val, int pa) { // 新建节点
    	int rt = ++id;
    	fa[rt] = pa; key[rt] = val; ch[rt][0] = ch[rt][1] = 0; tsize[rt] = 1;
    	return rt;
    }
    void pushup(int rt) { // 更新子树大小
    	tsize[rt] = tsize[ch[rt][0]] + tsize[ch[rt][1]] + 1;
    }
    void build(int &rt, int l, int r, int pa) { // 按下标建树
    	if (l>r) return;
    	int m = (l+r) >> 1;
    	rt = newnode(-1, pa);
    	build(ch[rt][0], l, m-1, rt); build(ch[rt][1], m+1, r, rt); // 建造左右儿子
    	pushup(rt); // 更新
    }
    int get(int x) { // 查询某个节点是它的祖先的左儿子还是右儿子
    	return ch[fa[x]][1]==x;
    }
    void rotate(int x) { // 旋转
    	int y = fa[x], d = get(x);
    	if (!y) return;
    	int z = fa[y], t = ch[x][d^1];
    	ch[y][d] = t; if (t) fa[t] = y;
    	fa[x] = z; if (z) ch[z][get(y)] = x;
    	ch[x][d^1] = y; fa[y] = x;
    	pushup(y); pushup(x);
    }
    void splay(int x, int f) { // 伸展
    	while (fa[x]!=f) {
    		int y = fa[x];
    		if (fa[y]==f) rotate(x);
    		else {
    			if (get(x)==get(y)) rotate(y);
    			else rotate(x);
    			rotate(x);
    		}
    	}
    	pushup(x); // 还要更新x
    	if (!f) root = x; // 如果f为0,把x设为根
    }
    int get_kth(int rt, int k) { // 查找第k个树的下标
    	int sz = tsize[ch[rt][0]]+1;
    	if (ksz) return get_kth(ch[rt][1], k-sz);
    	else return rt;
    }
    void insert(int pos, int val) { // 插入
    	int x = get_kth(root, pos+1), y = get_kth(root, pos+2);
    	splay(x, 0); splay(y, x); // 旋转,留出插入的空位
    	ch[y][0] = newnode(val, y); // 新建一个节点
    	pushup(y); pushup(x); // 更新子树大小
    }
    void dfs(int rt) { // 最后的输出
    	if (!rt) return;
    	dfs(ch[rt][0]);
    	if (key[rt]!=-1) printf("%d ", key[rt]);
    	dfs(ch[rt][1]);
    }
    int main() {
    	int n; scanf("%d", &n);
    	build(root, 1, 2, 0);
    	while (n--) {
    		int pos, val; scanf("%d%d", &pos, &val);
    		insert(pos, val);
    	}
    	dfs(root);
    	return 0;
    }

     

你可能感兴趣的:(刷题)