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:
",cas);
		for(int i=1;i<=m;i++){
			scanf("%lld",&x);
			printf("%lld
",Trie.query(x));
		}
	}
	return 0;
}

Hdu 5536

要求$(S_i+S_j) xor S_k$最大。
枚举$S_i$和$S_j$将其从Trie中删除,然后贪心查询。
复杂度$O(n^2log 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
",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;
}

codeforces 842 D

建好trie树后,建好1-3e5的字典树,插入修改标记。贪心查询。

对于修改,只需要按位看需不需要倒置就行。

#include<bits/stdc++.h>

#define lc (tire[id][0])
#define rc (tire[id][1])

using namespace std;

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);}

const int maxn = 6001000;
const int maxdep = 19;

bool rev[maxn];
int cnt[maxn];
int tire[maxn][2];
int rt,tot;
int build(int dep){
    int now=tot++;
    if(dep>=0){
        tire[now][0]=build(dep-1);
        tire[now][1]=build(dep-1);
    }
    return now;
}
int push_UP(int id){
    cnt[id]=min(cnt[lc],cnt[rc]);
}
int update(int id,int dep,int x){
    if(dep==-1){
        cnt[id]++;
        return 0;
    }
    int t=(x>>dep&1);
    update(tire[id][t],dep-1,x);
    push_UP(id);
}
void solve(){
    int ans=0;
    int now=rt;
    for(int i=maxdep;i>=0;i--){
        if(rev[i]){
            if(cnt[tire[now][1]]==0){
                now=tire[now][1];
            } else {
                now=tire[now][0];
                ans+=(1<<i);
            }
        } else {
            if(cnt[tire[now][0]]==0){
                now=tire[now][0];
            } else {
                now=tire[now][1];
                ans+=(1<<i);
            }
        }
    }
    printf("%d
",ans);
}
int n,m;
int main(){
	int x; 
    rt=build(maxdep);
    read(n,m); 
    for(int i=1;i<=n;i++){
        read(x);
        update(rt,maxdep,x);
    }
    for(int ii=1;ii<=m;ii++){
        read(x);
        for(int i=maxdep;i>=0;i--){
            if(x>>i&1){
                rev[i]^=1;
            }
        }
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/foreignbill/p/7858039.html