【参考了一些大佬:懒得放上来了..】
Trie实质上是字典树,查询字符串是否存在可以用字典树查询(来可以查询多少个)
这里我们用字典树查询Trie中的二进制串,异或值越大,代表高位差的越多,所以我们把数的二进制从高位记录。
并从高位开始尽量走相反的路,能保证最大。具体看代码。
D. Vasiliy's Multiset
这三题只给出第一题的代码。第二题和第一题类似,第三题就是把所有的先插进去,然后再跑一遍判断最大的。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxnode=100050*30;
const int sigma_size = 2;
int ch[maxnode][sigma_size];
int num[maxnode];
int val[maxnode];
struct Trie{
int sz;
void init()
{
sz=1;
memset(ch,0,sizeof(ch));
memset(val,-1,sizeof(val));
memset(num,0,sizeof(num));
}
void insert(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
num[u]++;
}
val[u]=x;
}
void del(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
u=ch[u][c];
if(num[u])num[u]--;
else return ;
}
}
int query(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(ch[u][c^1]&&num[ch[u][c^1]])u=ch[u][c^1];
else u=ch[u][c];
}
return val[u]^x;
}
bool is_in(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(ch[u][c]&&num[ch[u][c]])u=ch[u][c];
else return false;
}
return true;
}
}trie;
int main(){
int N;char st[10];
cin>>N;
trie.init();
trie.insert(0);
FOR(i,1,N){
scanf("%s",st);
int x;scanf("%d",&x);
if(st[0]=='+'){
trie.insert(x);
}
else if(st[0]=='-'){
trie.del(x);
}
else if(st[0]=='?'){
printf("%d\n",trie.query(x));
}
else printf("%d\n",trie.is_in(x));
}
}
POJ 3764
求树上的一条最大异或和路径
了解异或的一个性质:x^y=(x^z)^(y^z)
所以可以转换成dfs求出每个点到源点的异或和,再从中取出两个数异或值最大。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxnode=100050*31;
const int maxn=200100;
const int sigma_size = 2;
int ch[maxnode][sigma_size];
int num[maxnode];
int val[maxnode];
int dp[maxnode];
struct Edge{
int from,to,dist;
Edge(){}
Edge(int _from,int _to,int _dist):from(_from),to(_to),dist(_dist){}
};
int etop=1,he[maxn],ne[maxn];
Edge ed[maxn];
void add(int u,int v,int w){
ed[etop] = Edge(u, v, w);
ne[etop] = he[u];
he[u] = etop++;
}
void dfs(int u,int f){
for(int i=he[u];i;i=ne[i]){
Edge &e = ed[i];
if(e.to==f)continue;
//cout<<u<<"->"<<e.to<<endl;
dp[e.to]=dp[u]^e.dist;
dfs(e.to,u);
}
}
struct Trie{
int sz;
void init()
{
sz=1;
memset(ch,0,sizeof(ch));
memset(val,-1,sizeof(val));
memset(num,0,sizeof(num));
}
void insert(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
num[u]++;
}
val[u]=x;
}
void del(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
u=ch[u][c];
if(num[u])num[u]--;
else return ;
}
}
int query(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(ch[u][c^1]&&num[ch[u][c^1]])u=ch[u][c^1];
else u=ch[u][c];
}
return val[u]^x;
}
bool is_in(int x){
int u=0;
for(int i=31;i>=0;i--){
int c=(x>>i)&1;
if(ch[u][c]&&num[ch[u][c]])u=ch[u][c];
else return false;
}
return true;
}
}trie;
int A[500050];
int ind[500050];
int main(){
int N;
while(~scanf("%d",&N)){
etop=1;
memset(ind,0,sizeof(ind));
memset(he,0,sizeof(he));
memset(ne,0,sizeof(ne));
FOR(i,1,N-1){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ind[x+1]++,ind[y+1]++;
add(x+1,y+1,z);
add(y+1,x+1,z);
}
FOR(i,1,N)if(ind[i]==1){
add(0,i,0);
break;
}
dfs(0,-1);
trie.init();
FOR(i,1,N)trie.insert(dp[i]);
int maxx=-1;
FOR(i,1,N){
maxx=max(maxx,trie.query(dp[i]));
}
printf("%d\n",maxx);
}
}