zoukankan      html  css  js  c++  java
  • hdu 6191 可持久化trie||线段树套trie||trie启发式合并

    题意:一个树,q次询问,求xi xor u的子树的max值

    思路:考虑可以直接dfs,映射到数轴上,然后就是裸的可持久化trie了。。时间复杂度nlogn,同理nlognlogn可以线段树套trie(这个题没按这个写。。应该可以?参考51nod1295,第一次写可持久化trie就是树套树水过去的。。)同理,如果多个log时间复杂度可以就可以暴力启发式合并。。


    可持久化trie代码:

    #include <bits/stdc++.h>
    #define PB push_back
    #define MEM(x) memset(x,0,sizeof(x));
    using namespace std;
    char tmp[33];
    void tr(int x){
        tmp[32]='';
        for(int i=31;i>=0;i--){
            tmp[i]=((x&1)+'0');
            x>>=1;
        }
    }
    struct Trie_Persistent{
        const static int LetterSize = 2; 
        const static int TrieSize = 40 * ( 1e5 + 50); 
        int tot;
        struct node{
            int ptr[LetterSize];
            int cnt[LetterSize]; 
        }tree[TrieSize];
        inline int GetLetterIdx(int c){return c - '0';}
        int zinsert(const char * str ,int f){
            int len = strlen( str );
            int res = tot++; 
            tree[res] = tree[f]; 
            int cur = res; 
            for(int i = 0 ; i < len ; ++ i){
                int idx = GetLetterIdx( str[i] ); 
                int p = tot ++ ; 
                tree[cur].cnt[idx] ++ ;
                tree[cur].ptr[idx] = p;
                f = tree[f].ptr[idx]; 
                tree[p] = tree[f]; 
                cur = tree[cur].ptr[idx]; 
            }
            return res;
        }
        int zfind(const char * str , int l ,int r){
            int len = strlen(str);
            int ret=0;
            for(int i = 0 ; i < len ; ++ i){
                int idx = (GetLetterIdx(str[i]));
                int cnt = tree[r].cnt[idx^1] - tree[l].cnt[idx^1];
                if(cnt==0){
                    l = tree[l].ptr[idx];
                    r = tree[r].ptr[idx];
                }
                else{
                    ret|=(1<<(31-i));
                    l = tree[l].ptr[idx^1];
                    r = tree[r].ptr[idx^1];
                }
            }
            return ret;
        }
        void init(){
            tot = 1;
            for(int i = 0 ; i < LetterSize ; ++ i)
                tree[0].ptr[i] = 0 , tree[0].cnt[i] = 0;
        }
    }trie;
    const int maxn=1e6+7;
    int a[maxn],R[maxn],L[maxn],tim,n,q,x,y;
    int root[maxn];
    vector<int> e[maxn];
    void dfs(int x){
        L[x]=tim;
        for(int i=0;i<e[x].size();i++)
            dfs(e[x][i]);
        R[x]=tim++;
        tr(a[x]);
        root[R[x]]=trie.zinsert(tmp,root[R[x]-1]);
    }
    int main(){
        while(scanf("%d%d",&n,&q)!=EOF){
            tim=1;MEM(root);
            for(int i=1;i<=n;i++)  scanf("%d",&a[i]),e[i].clear();
            for(int i=1;i<n;i++) scanf("%d",&x),e[x].PB(i+1);
            trie.init();
            dfs(1);
            for(int i=1;i<=n;i++){
                scanf("%d%d",&x,&y);
                tr(y);
                printf("%d
    ",trie.zfind(tmp,root[L[x]-1],root[R[x]]));
            }
        }
        return 0;
    }
    


  • 相关阅读:
    [LintCode 614.] 二叉树的最长连续子序列 II
    [LintCode 90.] k数和 II
    [LintCode 1674.] 倒可乐
    [LintCode 797.] 到达一个数字
    [LintCode 1691.] 买卖股票的最佳时机V
    [LintCode 69. 242.] 二叉树的层次遍历
    [LintCode 229.] 栈排序
    [LeetCode 1671.] 玩游戏
    [LintCode 1668.] 区间最小覆盖
    (十)线程同步
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672489.html
Copyright © 2011-2022 走看看