01字典树

Hdu 4825

从高位到地位建立字典树,贪心查询。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100000+5;
typedef long long ll;
ll bin[35];
int n,m;
ll a[maxn],x;

struct trie{
    int cnt;
    int ch[maxn*35][2];
    ll val[maxn*35];
    void init(){
        cnt=1;
        memset(ch[0],0,sizeof ch[0]);
    }
    void insert(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(!ch[u][t]){
                memset(ch[cnt],0,sizeof ch[cnt]);
                val[cnt]=0;
                ch[u][t]=cnt++;
            }
            u=ch[u][t];
        }
        val[u]=a;
    }
    ll query(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(ch[u][t^1]) u=ch[u][t^1];
            else u=ch[u][t];
        }
        return val[u];
    }
}Trie;

int main(){
    //freopen("in.txt","r",stdin);
    bin[0]=1;for(ll i=1;i<=35;i++) bin[i]=bin[i-1]*2ll;
    int T,cas=1;
    for(cin>>T,cas=1;cas<=T;cas++){
        scanf("%d%d",&n,&m);
        Trie.init();
        for(int i=1;i<=n;i++){
            scanf("%lld",&x);
            Trie.insert(x);
        }
        printf("Case #%d:\n",cas);
        for(int i=1;i<=m;i++){
            scanf("%lld",&x);
            printf("%lld\n",Trie.query(x));
        }
    }
    return 0;
}

Hdu 5536

要求$(S_i+S_j) xor S_k$最大。
枚举$S_i$和$S_j$将其从Trie中删除,然后贪心查询。
复杂度$O(n^2\log n)$.

#include <bits/stdc++.h>

using namespace std;
const int maxn = 10000+5;
typedef long long ll;
ll bin[35];
int n,m;
ll a[maxn],x;

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}
template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

struct trie{
    int cnt;
    int ch[maxn*35][2];
    ll val[maxn*35];
    int ts[maxn*35];
    inline void init(){
        cnt=1;
        memset(ch[0],0,sizeof ch[0]);
        ts[0]=0;
        //memset(ts,0,sizeof ts);
    }
    inline void insert(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(!ch[u][t]){
                memset(ch[cnt],0,sizeof ch[cnt]);
                val[cnt]=0;
                ts[cnt]=0;
                ch[u][t]=cnt++;
            }
            u=ch[u][t];
            ts[u]++;
        }
        val[u]=a;
    }
    inline void del(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            u=ch[u][t];
            ts[u]--;
        }
    }
    inline ll query(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(ch[u][t^1]&&ts[ch[u][t^1]]) u=ch[u][t^1];
            else u=ch[u][t];
        }
        return val[u]^a;
    }
}Trie;

int main(){
    //freopen("in.txt","r",stdin);
    bin[0]=1;for(ll i=1;i<=35;i++) bin[i]=bin[i-1]*2ll;
    int T,cas=1;
    for(cin>>T,cas=1;cas<=T;cas++){
        scanf("%d",&n);
        Trie.init();
        for(int i=1;i<=n;i++){
            read(a[i]);
            Trie.insert(a[i]);
        }
        ll mx=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                Trie.del(a[i]);Trie.del(a[j]);
                mx=max(mx,Trie.query(a[i]+a[j]));
                Trie.insert(a[i]);Trie.insert(a[j]);
            }
        printf("%lld\n",mx);
    }
    return 0;
}

Bzoj 4260

正做一遍dp,倒着做一遍dp。类似合唱队型。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 400000+5;
typedef long long ll;
int bin[31];
int n,m;
int a[maxn],x;
int dp[maxn],df[maxn];

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

struct trie{
    int cnt;
    int ch[maxn*31][2];
    int val[maxn*31];
    void init(){
        cnt=1;
        memset(ch[0],0,sizeof ch[0]);
    }
    void insert(int a){
        int u=0;
        for(int i=32;i>=0;i--){
            int t=a&bin[i];t>>=i;
            if(!ch[u][t]){
                memset(ch[cnt],0,sizeof ch[cnt]);
                val[cnt]=0;
                ch[u][t]=cnt++;
            }
            u=ch[u][t];
        }
        val[u]=a;
    }
    int query(int a){
        int u=0;
        for(int i=32;i>=0;i--){
            int t=a&bin[i];t>>=i;
            if(ch[u][t^1]) u=ch[u][t^1];
            else u=ch[u][t];
        }
        return val[u]^a;
    }
}Trie;

int main(){
    //freopen("in.txt","r",stdin);
    bin[0]=1;for(int i=1;i<=35;i++) bin[i]=bin[i-1]*2;
    read(n);
    for(int i=1;i<=n;i++)
        read(a[i]);
    Trie.init();
    Trie.insert(0);
    x=0;
    for(int i=1;i<=n;i++){
        x=x^a[i];
        dp[i]=Trie.query(x);
        Trie.insert(x);
    }
    Trie.init();
    Trie.insert(0);
    x=0;
    for(int i=n;i>=1;i--){
        x^=a[i];
        df[i]=Trie.query(x);
        Trie.insert(x);
    }
    ll mx=0;
    ll res=0;
    for(int i=1;i<=n;i++){
        mx=max(mx,(ll)dp[i]);
        res=max(res,mx+df[i+1]);
    }
    cout<<res<<endl;
    return 0;
}
时间: 2024-08-05 20:34:30

01字典树的相关文章

HDU6191(01字典树启发式合并)

Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 801    Accepted Submission(s): 302 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey

2014百度之星资格赛—— Xor Sum(01字典树)

Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起

01字典树贪心查询+建立+删除(个人模版)

01字典树贪心查询+建立+删除: 1 #define maxn 2 2 typedef struct tree 3 { 4 tree *nex[maxn]; 5 int v; 6 int val; 7 }tree; 8 tree root; 9 void init() 10 { 11 for(int i=0;i<maxn;i++) 12 { 13 root.nex[i]=NULL; 14 } 15 } 16 void creat(char *str,int va) 17 { 18 int len

[01字典树]求序列完美度(求区间最大异或值)

https://nanti.jisuanke.com/t/15531 解题关键:01字典树模板,用字典树保存每个数的二进制表示,从而动态维护区间上的最大异或值,注意添加和删除都可以用于一个change函数表示. 复杂度:$O(n\log n + {n^2}\log n)$ 1 #include<bits/stdc++.h> 2 #define maxn 1005 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 typedef long lon

Chip Factory---hdu5536(异或值最大,01字典树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536 题意:有一个数组a[], 包含n个数,从n个数中找到三个数使得 (a[i]+a[j])⊕a[k]最大,i,j,k不同; 求异或的结果最大所以我们可以用01字典树,先把所有的数加入字典树中,从n个数中选出两个数a[i]和a[j], 先把他们从字典树中删除,然后找到与a[i]+a[j]异或最大的数,和结果取最大值即可: 最后不要忘记再把a[i]和a[j]添加到字典树中即可: #include<st

HDU 4825 Xor Sum 【01字典树】

题面: Problem Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数据,每组

HDU4825/5536 [01 字典树/简单字典树更新]

Xor Sum Time Limit: 1000 MS Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数

异或最大值(01字典树)

/** 异或最大值(01字典树) 题意:求n个非负数中任意2个的异或值的最大值.n数量级为10^5 分析:直接暴力肯定超时了.一个非负整数可以看成1个32位的01字符串,n个数可以看成n个字符串,因此可以建立字典树, 建好树后,对于任意非负整数x,可以沿着树根往下贪心找到y,使得x异或y最大,复杂度为树的深度. */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iost

01字典树及其模板

模板 : const int Bit = 32; struct Trie { Trie *ch[2]; LL v; inline void init(){ for(int i=0; i<2; i++) this->ch[i] = NULL; this->v = -1; } }; Trie *root;///记得在 main 函数的时候分配空间给 root 并初始化 inline void CreateTrie(LL x) { Trie * p = root, *tmp; for(int

HDU 4825 Xor Sum(01字典树入门题)

http://acm.hdu.edu.cn/showproblem.php?pid=4825 题意: 给出一些数,然后给出多个询问,每个询问要从之前给出的数中选择异或起来后值最大的数. 思路:将给出的数建立01字典树,从高位开始建树.对于每个询问,如果当前位置值为0,那么在字典树中,如果有1的值,那么就优先走1,否则再走0. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using names