题干
- 玩具装箱
(eirt.cpp/c/pas)
【问题描述】
你有两堆物品分别有n1,n2个,每个物品有两个属性ai,bi。你要从两堆中分别选一个物品,满足a1^a2<=m( ^表示异或)的前提下最大化b1+b2。
【输入格式】
输入文件名为eirt.in。
第一行包含 3 个整数 n1,n2,m。
接下来的 n1行每行包含两个整数ai,bi。
接下来的 n2 行每行包含两个整数ai,bi。
【输出格式】
输出文件名为eirt.out。
输出1行最大sum。
【样例输入】
1 1 1
1 2
1 2
【样例输出】
4
【数据规模与约定】
对于50% 的数据:1<n1,n2≤1000。
对于100% 的数据:1<n1,n2≤10^ 5 , 1<=ai,bi,m<=2^30-1 。
solution
- 我们把n1里的a值建一个01trie树,把a1的末尾赋为b1。
- 我们再用dfs+回溯求出这个点子树中最大的b1值,记为mx[i]
- 好了,现在我们有一个包含n1所有信息的trie树,我们考虑枚举n2的每一个a2,只要在trie树中找一个合法的a1且这个a1的b1最大就行(我们把这个b1加上n2中a2的b2,再在所有b1+b2中取最大值即可
- 如何??
- 我们把m认为是代价,对于a2的每一位,走与a2相同的边一定不花费代价,走不相同的会花费1<<深度 的代价。
- 如果可以走不相同的边,那相同边所对应的那一部分子树一定在m的代价内都能达到,所以直接取max(ans,mx[])。如果可以走不相同的边,那相同边所对应的那一部分子树一定在m的代价内都能达到,所以直接取max(ans,mx[])。
- 如果不行,那么递归求解相同的那一部分子树
附trie树练习
https://blog.csdn.net/zuzhiang/article/details/79872805
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
inline int read(){
char ch=' ';int f=1;int x=0;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int tol;
int val[32*N];
int ch[32*N][2];
void init()
{
tol=1;
ch[0][0]=ch[0][1]=0;
val[0]=0;
}
void insert(int x,int y)
{
int u=0;
for(int i=30;i>=0;i--)
{
int v=(x>>i)&1;
if(!ch[u][v])
{
ch[tol][0]=ch[tol][1]=0;
val[tol]=0;
ch[u][v]=tol++;
}
u=ch[u][v];
}
val[u]=max(val[u],y);
}
int mx[32*N];
void dfs(int u)
{
if(val[u])
{
mx[u]=val[u];
return ;
}
if(ch[u][0])
{
dfs(ch[u][0]);
mx[u]=max(mx[u],mx[ch[u][0]]);
}
if(ch[u][1])
{
dfs(ch[u][1]);
mx[u]=max(mx[u],mx[ch[u][1]]);
}
}
int query(int x,int mm)
{
int ret=0;
int u=0;
for(int i=30;i>=0;i--)
{
int v=(x>>i)&1;
int tmp=(1<<i);
if(mm-tmp>=0)
{
if(ch[u][v])
ret=max(ret,mx[ch[u][v]]);
u=ch[u][v^1];
mm-=tmp;
}
else
{
u=ch[u][v];
}
if(u==0) break;
if(i==0) ret=max(ret,mx[u]);
}
return ret;
}
int main()
{
//freopen("eirt.in","r",stdin);
//freopen("eirt.out","w",stdout);
int n1,n2,m;
n1=read();n2=read();m=read();
int i,j;
int x,y;
init();
for(i=1;i<=n1;i++)
{
x=read();y=read();
insert(x,y);
}
dfs(0);
int ans=0;
for(i=1;i<=n2;i++)
{
x=read();y=read();
int tmp=query(x,m);
if(tmp!=0)
ans=max(ans,tmp+y);
}
printf("%d\n",ans);
return 0;
}