zoukankan      html  css  js  c++  java
  • HDU 6191 Query on A Tree(可持久化Trie)

    题意

    (n) 个点的有根树,根为 (1) 。每个点有点权,有 (q) 个询问,每次询问以 (u) 为根的子树的点的点权中异或 (x) 所得的最大值是多少。

    思路

    求出整棵树的 ( ext{dfs}) 序,问题就转化成了序列上,求一个区间中的数字异或 (x) 可得的最大值。同样的方法,只需在原序列上建立可持久化的 ( ext{Trie}) 树即可,和区间第 (K) 值类似的方法,在 ”主席( ext{Trie}) “上找最大解。

    代码

    #include<bits/stdc++.h>
    #define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
    #define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
    typedef long long LL;
    using namespace std;
    const int N=1e5+5;
    template<const int maxn,const int maxm>struct Linked_list
    {
    	int head[maxn],to[maxm],nxt[maxm],tot;
    	Linked_list(){clear();}
    	void clear(){memset(head,-1,sizeof(head));tot=0;}
    	void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
    	#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
    };
    Linked_list<N,N>G;
    struct Trie
    {
    	struct node{int son[2],sum;};
    	node nd[N*32];
    	int rt[N],tot;
    	int &operator [](const int x){return rt[x];}
    	void build()
    	{
    		memset(rt,0,sizeof(rt));
    		nd[tot=0]=(node){0,0,0};
    	}
    	void create(int &k){nd[++tot]=nd[k],k=tot;}
    	void insert(int &k,int x,int n)
    	{
    		create(k),nd[k].sum++;
    		if(n<0)return;
    		insert(nd[k].son[x>>n&1],x&((1<<n)-1),n-1);
    	}
    	int query(int k,int p,int x,int n)
    	{
    		if(n<0)return 0;
    		if(nd[nd[k].son[~x>>n&1]].sum-nd[nd[p].son[~x>>n&1]].sum>0)
    			return (1<<n)|query(nd[k].son[~x>>n&1],nd[p].son[~x>>n&1],x&((1<<n)-1),n-1);
    		else return query(nd[k].son[x>>n&1],nd[p].son[x>>n&1],x&((1<<n)-1),n-1);
    	}
    }Tr;
    int n,q,p[N],L[N],R[N],ori[N],ord;
    
    void dfs(int u,int f)
    {
    	L[u]=++ord,ori[ord]=u;
    	EOR(i,G,u)
    	{
    		int v=G.to[i];
    		if(v==f)continue;
    		dfs(v,u);
    	}
    	R[u]=ord;
    }
    
    int main()
    {
    	while(~scanf("%d%d",&n,&q))
    	{
    		Tr.build();
    		G.clear();
    		FOR(i,1,n)scanf("%d",&p[i]);
    		FOR(v,2,n)
    		{
    			int u;
    			scanf("%d",&u);
    			G.add(u,v);
    		}
    		ord=0;
    		dfs(1,0);
    		FOR(i,1,n)Tr.insert(Tr[i]=Tr[i-1],p[ori[i]],30);
    		while(q--)
    		{
    			int u,x;
    			scanf("%d%d",&u,&x);
    			printf("%d
    ",Tr.query(Tr[R[u]],Tr[L[u]-1],x,30));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    php判断是不是https的方法
    [Redis] Redis哨兵模式部署
    Transformer详解:各个特征维度分析推导
    Hell World:)
    cesiumjs
    UVA-11090 Going in Cycle!!
    判断两个数组是否相似 (arraysSimilar)
    Markdown 语法说明 (简体中文版)
    DjangoModels
    Lua 学习 chapter30 编写c函数的技巧
  • 原文地址:https://www.cnblogs.com/Paulliant/p/10159041.html
Copyright © 2011-2022 走看看