• Box HDU


    Box

    [Time Limit: 5000 ms quad Memory Limit: 32768 kB ]

    题意

    给出 (n) 个箱子的包含关系,每次两种操作。
    操作 (1):把 (x) 的箱子及里面的箱子一块挪到 (y) 箱子里面去。
    操作 (2):查询 (x) 箱子的最外层的箱子编号。

    思路

    对于每一大块箱子,可以看成树和子树的包含关系,那么可以根据树的 (dfs) 序,把一个箱子所包含的箱子拍成一个区间,这样就变成了很多颗树。为了方便后面的操作,对于每个箱子 (x) 所包含的区间,用标号 (x) 来表示开始的位置,(x+n) 来表示结束的位置。

    使用 (splay) 维护每多颗树的 (dfs) 序。由于每棵树都有一个自己的 (root) 节点,我们让他们的 (root) 节点统一连向 (0) 这个虚点。

    再来看一看操作,操作 (1) 可以变成删除操作以及区间移动操作。操作 (2) 就是普通的查询操作。

    对于操作 (1),先找到 (x)(x+n) 所在的位置,把 (x) (splay) 到其树的 (root) 上,把 (x+n) (slay)(x) 的右子树上,那么我们要转移的树就是 (x->x+n->x+n)的所有左子树。 同样的,要查找非法条件,只要看 (y) 在不在这棵树里面就可以了。
    最后只要把这棵树插到标号 (y) 的右边就可以了。可以先把 (y) (splay) 到其 (root) 上,然后找到 (y) 下标意义上的后继,然后插入就行了。

    对于操作(2),只要把 (x) (splay) 到其树的 (root) 上,然后查询这棵树里面的最小标号是多少,也就找到了最外的箱子的标号。

    /*************************************************************** 
      > File Name    : a.cpp
      > Author       : Jiaaaaaaaqi
      > Created Time : Mon 14 Oct 2019 07:20:55 PM CST
     ***************************************************************/
    
    #include <map>
    #include <set>
    #include <list>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pb         push_back
    #define  pii        pair<int, int>
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 1e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    vector<int> vv[maxn];
    int root, tot;
    int ch[maxn][2];
    int sz[maxn], fa[maxn], val[maxn], cnt[maxn];
    int a[maxn], id[maxn];
    
    void init() {
    	tol = root = tot = 0;
    	for(int i=0; i<=n; i++) {
    		vv[i].clear();
    	}
    } 
    
    int newnode(int x, int f) {
    	mes(ch[++tot], 0);
    	val[tot] = x;
    	id[x] = tot;
    	fa[tot] = f;
    	sz[tot] = cnt[tot] = 1;
    	return tot;
    }
    
    void pushdown(int x) { }
    
    void pushup(int x) {
    	if(x) {
    		sz[x] = cnt[x];
    		if(ch[x][0])	sz[x] += sz[ch[x][0]];
    		if(ch[x][1])	sz[x] += sz[ch[x][1]];
    	}
    }
    
    int get(int x) {
    	return ch[fa[x]][1] == x;
    }
    
    void rotate(int x) {
    	int f = fa[x], gf = fa[f], k = get(x), w = ch[x][k ^ 1];
    	pushdown(f), pushdown(x);
    	ch[f][k] = w, fa[w] = f;
    	ch[gf][get(f)] = x, fa[x] = gf;
    	ch[x][k ^ 1] = f, fa[f] = x;
    	pushup(f), pushup(x);
    }
    
    void splay(int x, int goal = 0) {
    	int f, gf;
    	while (fa[x] != goal) {
    		f = fa[x], gf = fa[f];
    		pushdown(gf), pushdown(f), pushdown(x);
    		if (gf != goal) {
    			if(get(x) == get(f)) rotate(f);
    			else rotate(x);
    		}
    		rotate(x);
    	}
    	if (!goal) root = x;
    }
    
    int build(int l, int r, int f) {
    	if(l > r)	return 0;
    	int mid = l+r>>1;
    	int now = newnode(a[mid], f);
    	ch[now][0] = build(l, mid-1, now);
    	ch[now][1] = build(mid+1, r, now);
    	pushup(now);
    	return now;
    }
    
    void dfs(int u) {
    	a[tol++] = u;
    	for(auto v : vv[u]) {
    		dfs(v);
    	}
    	a[tol++] = u+n;
    }
    
    void Move(int a, int b) {
    	if(a == b)	return ;
    	int x = id[a], y = id[a+n], z = id[b];
    	splay(x), splay(y, x);
    	while(z && z!=y) {
    		if(ch[y][0] == z)	return ;
    		z = fa[z];
    	}
    	if(ch[x][0]==0 || ch[y][1]==0) {
    		fa[ch[x][0]+ch[y][1]] = 0;
    	} else {
    		int k = ch[y][1];
    		while(ch[k][0])	k = ch[k][0];
    		splay(k, y);
    		int cur = ch[y][1];
    		ch[cur][0] = ch[x][0];
    		fa[ch[x][0]] = cur;
    		fa[cur] = 0;
    		pushup(cur);
    	}
    	ch[x][0] = ch[y][1] = 0;
    	if(b == 0)	return ;
    	z = id[b];
    	splay(z);
    	if(ch[z][1]) {
    		z = ch[z][1];
    		while(ch[z][0])	z = ch[z][0];
    	}
    	ch[z][0] = x;
    	fa[x] = z;
    	pushup(z);
    }
    
    void Query(int x) {
    	x = id[x];
    	splay(x);
    	while(ch[x][0])	x = ch[x][0];
    	printf("%d
    ", val[x]);
    }
    
    int main() {
    	// freopen("in", "r", stdin);
    	int flag = 0;
    	while(~scanf("%d", &n)) {
    		if(flag)	printf("
    ");
    		flag = 1;
    		init();
    		for(int i=1; i<=n; i++) {
    			int x;
    			scanf("%d", &x);
    			vv[x].pb(i);
    		}
    		dfs(0);
    		tol--;
    		// for(int i=1; i<tol; i++)	printf("%d%c", a[i], i==tol-1 ? '
    ':' ');
    		int st = 1, c = 0;
    		for(int i=1; i<tol; i++) {
    			if(a[i] <= n)	c++;
    			else	c--;
    			if(c == 0) {
    				build(st, i, 0);
    				st = i+1;
    			}
    		}
    		// for(int i=1; i<=tot; i++)	printf("val[%d] = %d
    ", i, val[i]);
    		scanf("%d", &m);
    		char s[10];
    		while(m--) {
    			int x, y;
    			scanf("%s", s+1);
    			if(s[1] == 'M') {
    				scanf("%d%d", &x, &y);
    				Move(x, y);
    			} else {
    				scanf("%d", &x);
    				Query(x);
    			}
    		}
    	}
    }
    
  • 相关阅读:
    solr初步了解
    jieba初步了解
    情感计算emokit
    常用命令
    java跨域访问问题记录
    mysql 免安装版配置
    Android 图片缩放方法
    spring android http
    sql join 与where的区别
    android activitygroup 使用
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11695992.html
Copyright © 2020-2023  润新知