zoukankan      html  css  js  c++  java
  • P4592 [TJOI2018]异或 可持久化0/1Trie树

    对于一段区间查询最大异或值,我们可以用 可持久化0/1Trie树 来维护。

    对于一个点的子树,它们的 (dfs) 序是一段连续的区间。

    对于一条路经,我们拆成两个端点分别到达 (LCA) 的两条路径,它们的 (dep) 是连续的。

    我们分别建出来 1.以 (dfs) 序为外层的树 2.以 (dep) 为外层的树 这两种树即可。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n, q, x, y, z, tot, DFN, opt, cnt, lca;
    const int N = 100010;
    int head[N], to[N << 1], nt[N << 1], v[N], dfn[N], nfd[N], siz[N], son[N], top[N], dep[N], fa[N], root1[N], root2[N], tr[N * 63][2], sum[N * 63];
    void add(int f, int t)
    {
    	to[++tot] = t; nt[tot] = head[f]; head[f] = tot;
    }
    void Insert(int pre, int &k, int x, int t)
    {
    	k = ++cnt; sum[k] = sum[pre] + 1;
    	if (!t)return;
    	int i = (x >> (t - 1)) & 1;
    	tr[k][!i] = tr[pre][!i]; Insert(tr[pre][i], tr[k][i], x, t - 1);
    }
    int ask(int pre, int k, int x, int t)
    {
    	if (!t)return 0;
    	int i = x >> (t - 1) & 1;
    	if (sum[tr[k][!i]] > sum[tr[pre][!i]])return (1 << (t - 1)) | ask(tr[pre][!i], tr[k][!i], x, t - 1);
    	else return ask(tr[pre][i], tr[k][i], x, t - 1);
    }
    void dfs1(int x, int f)
    {
    	Insert(root1[f], root1[x], v[x], 30); //父子
    	fa[x] = f; siz[x] = 1; dep[x] = dep[f] + 1;
    	for (int i = head[x]; i; i = nt[i])
    		if (to[i] != f)
    		{
    			dfs1(to[i], x);
    			siz[x] += siz[to[i]];
    			if (siz[to[i]] > siz[son[x]])son[x] = to[i];
    		}
    }
    void dfs2(int x, int t)
    {
    	top[x] = t; dfn[x] = ++DFN; nfd[DFN] = x;
    	Insert(root2[nfd[DFN - 1]], root2[x], v[x], 30); //子树
    	if (son[x])dfs2(son[x], t);
    	else return;
    	for (int i = head[x]; i; i = nt[i])
    		if (to[i] != fa[x] && to[i] != son[x])dfs2(to[i], to[i]);
    }
    int LCA(int x, int y)
    {
    	while (top[x] != top[y])
    	{
    		if (dep[top[x]] < dep[top[y]])swap(x, y);
    		x = fa[top[x]];
    	}
    	return dep[x] < dep[y] ? x : y;
    }
    int main()
    {
    	cin >> n >> q;
    	for (int i = 1; i <= n; ++i)scanf("%d", &v[i]);
    	for (int i = 1; i < n; ++i)
    	{
    		scanf("%d%d", &x, &y);
    		add(x, y); add(y, x);
    	}
    	dfs1(1, 0); dfs2(1, 1);
    	while (q--)
    	{
    		scanf("%d", &opt);
    		if (opt == 1)
    		{
    			scanf("%d%d", &x, &z);
    			printf("%d
    ", ask(root2[nfd[dfn[x] - 1]], root2[nfd[dfn[x] + siz[x] - 1]], z, 30));
    		}
    		else
    		{
    			scanf("%d%d%d", &x, &y, &z);
    			lca = LCA(x, y);
    			printf("%d
    ", max(ask(root1[fa[lca]], root1[x], z, 30), ask(root1[fa[lca]], root1[y], z, 30)));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    stenciljs 学习四 组件装饰器
    stenciljs 学习三 组件生命周期
    stenciljs 学习二 pwa 简单应用开发
    stenciljs ionic 团队开发的方便web 组件框架
    stenciljs 学习一 web 组件开发
    使用npm init快速创建web 应用
    adnanh webhook 框架 hook rule
    adnanh webhook 框架 hook 定义
    adnanh webhook 框架request values 说明
    adnanh webhook 框架execute-command 以及参数传递处理
  • 原文地址:https://www.cnblogs.com/wljss/p/12601445.html
Copyright © 2011-2022 走看看