• HDU6191 Query on A Tree (01字典树+启发式合并)


    题意:

    给你一棵1e5的有根树,每个节点有点权,1e5个询问(u,x),问你子树u中与x异或最大的值是多少

    思路:

    自下而上启发式合并01字典树,注意合并时清空trie

    线段树、字典树这种结构确定的数据结构,启发式合并的时候不需要考虑次序,复杂度都是nlogn

    代码:

    2200 / 10000ms , 60 / 128 M

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    #define LLONG_MAX 9223372036854775807
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e6+11;
    const int maxm = 1e5+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int tot;
    int n, q;
    int a[maxm];
    int root[maxm];
    int trie[maxn][2];
    vector<int>v[maxm];
    queue<int>pool;
    int build(){
        if(!pool.empty()){
            int x = pool.front();
            pool.pop();
            return x;
        }
        ++tot;
        return tot;
    }
    void insert(int root, int t){
        for(int i = 31; i >= 0; i--){
            int x = (t>>i)&1;
            if(!trie[root][x])trie[root][x]=build();
            root = trie[root][x];
        }
        return;
    }
    int query(int root, int t){
        int ans = 0;
        for(int i = 31; i >= 0; i--){
            int x = (t>>i)&1;
            if(trie[root][x^1]){
                ans|=(1<<i);
                root = trie[root][x^1];
            }
            else root = trie[root][x];
        }
        return ans;
    }
    vector<PI>ask[maxn];
    void del(int x){
        if(!x)return;
        pool.push(x);
        return;
    }
    int merge(int p, int q){
        if(!p)return q;
        if(!q)return p;
        trie[p][0] = merge(trie[p][0], trie[q][0]);
        trie[p][1] = merge(trie[p][1], trie[q][1]);
        trie[q][0]=trie[q][1]=0;
        del(q);
        return p;
    }
    int ans[maxn];
    void dfs(int x){
        root[x] = build();
        insert(root[x], a[x]);
        for(int i = 0; i < (int)v[x].size(); i++){
            int y = v[x][i];
            dfs(y);
            root[x] = merge(root[x],root[y]);
        }
        for(int i = 0; i < (int)ask[x].size(); i++){
            ans[ask[x][i].fst] = query(root[x], ask[x][i].sc);
        }
        return;
    }
    
    int main(){
        while(~scanf("%d %d", &n, &q)){  
            tot = 0;
            while(!pool.empty())pool.pop();
            mem(trie,0);
            for(int i = 1; i <= n; i++){
                v[i].clear();
                ask[i].clear();
                root[i]= 0;
                scanf("%d", &a[i]);
            }
            for(int i = 2; i <= n; i++){
                int x;
                scanf("%d", &x);
                v[x].pb(i);
            }
            for(int i = 1; i <= q; i++){
                int u, x;
                scanf("%d %d", &u, &x);
                ask[u].pb(make_pair(i,x));
            }
            dfs(1);
            for(int i = 1; i <= q; i++){
                printf("%d
    ",ans[i]);
            }
            del(root[1]);
        }
        return 0;
    }
    /*
    2 2
    1 2
    1
    1 3
    2 1
    
    3 2
    1 2 3
    1 1
    3 4
    1 3
    
    11 4
    1 2 3 4 5 6 7 8 9 10 11
    1 1 1 2 2 3 4 4 4 5
    2 5
    3 6
    1 2
    8 7
    
    100000 2
    1 55
    2 33
     */
  • 相关阅读:
    Android和kernel杂散点集合
    Kernel的IIC驱动分析
    Uboot流程分析
    关于在eclipse当中,对接口方法的实现使用@Override报错的解决方式
    任务调度工具oozie和azkaban的对比
    实现Linux和windows之间实现文件传输的问题解决方式。sftp和ftp
    使用spring-boot创建定时任务。同时创建多线程执行定时任务。
    【C++11】新特性——auto的使用
    Inline函数使用注意事项
    结构体变量的sizeof计算
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10807276.html
Copyright © 2020-2023  润新知