zoukankan      html  css  js  c++  java
  • HDU6191 Query on A Tre【dsu on tree + 01字典树】

    Query on A Tree

    Problem Description
    Monkey A lives on a tree, he always plays on this tree.

    One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.

    Monkey A gave a value to each node on the tree. And he was curious about a problem.

    The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).

    Can you help him?

    给出一棵根为(1)的树,每个点都有权值,(q)次询问,每次询问以(u)为根的子树里和(x)异或的最大值是多少
    如果询问是以(1)为根的话,我们可以直接把所有点放到(01)字典树里去,然后每次拿(x)去匹配
    现在不是以(1)为根,可以考虑树上启发式合并,先处理轻儿子,然后处理重儿子,保留重儿子的子树建出来的字典树,然后把其他子树里的点放进去
    从高位到低位贪心匹配即可

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int n,w[MAXN],q,son[MAXN],sz[MAXN],ret[MAXN];
    vector<int> G[MAXN];
    vector<pair<int,int> > Q[MAXN];
    struct Trie{
        int tot,ch[MAXN<<4][2];
        void clear(){ tot = 0, ch[0][0] = ch[0][1] = 0; }
        int newnode(){ tot++; ch[tot][0] = ch[tot][1] = 0; return tot; }
        void insert(int x){
            int p = 0;
            for(int i = 30; ~i; i--){
                int nxt = (x&(1<<i))?1:0;
                if(!ch[p][nxt]) ch[p][nxt] = newnode();
                p = ch[p][nxt];
            }
        }
        int match(int x){
            int res = 0, p = 0;
            for(int i = 30; ~i; i--){
                int nxt = (x&(1<<i))?0:1;
                if(ch[p][nxt]) res |= (1<<i), p = ch[p][nxt];
                else p = ch[p][nxt^1];
            }
            return res;
        }
    }trie;
    void dfs(int u){
        sz[u] = 1; son[u] = 0;
        for(int v : G[u]){
            dfs(v); sz[u] += sz[v];
            if(sz[v]>sz[son[u]]) son[u] = v;
        }
    }
    void update(int u){
        trie.insert(w[u]);
        for(int v : G[u]) update(v);
    }
    void search(int u, bool clear){
        for(int v : G[u]) if(v!=son[u]) search(v,true);
        if(son[u]) search(son[u],false);
        for(int v : G[u]) if(v!=son[u]) update(v);
        trie.insert(w[u]);
        for(auto que : Q[u]) ret[que.second] = trie.match(que.first);
        if(clear) trie.clear();
    }
    void solve(){
        for(int i = 1; i <= n; i++){
            G[i].clear(); Q[i].clear();
            scanf("%d",&w[i]);
        }
        for(int i = 2; i <= n; i++){
            int par; scanf("%d",&par);
            G[par].emplace_back(i);
        }
        dfs(1);
        for(int i = 1; i <= q; i++){
            int u, x; scanf("%d %d",&u,&x);
            Q[u].emplace_back(make_pair(x,i));
        }
        search(1,true);
        for(int i = 1; i <= q; i++) printf("%d
    ",ret[i]);
    }
    int main(){
        while(scanf("%d %d",&n,&q)!=EOF) solve();
        return 0;
    }
    
  • 相关阅读:
    Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
    Android-自定义dialog
    安卓签名
    安卓 textview 换行 不满就换了
    [android] setOnTouchEvent 设置返回值为true 和 false的区别
    图片自动切换, 滑动循环切换图片
    Android访问中央气象台的天气预报API得到天气数据
    android:windowSoftInputMode属性详解
    Android中资源文件夹res/raw和assets的使用
    WPF基础学习笔记整理 (二) XAML
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12774138.html
Copyright © 2011-2022 走看看