11.1二中校内模拟赛T1 trie树+递归

题干

  1. 玩具装箱
    (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

  1. 我们把n1里的a值建一个01trie树,把a1的末尾赋为b1。
  2. 我们再用dfs+回溯求出这个点子树中最大的b1值,记为mx[i]
  3. 好了,现在我们有一个包含n1所有信息的trie树,我们考虑枚举n2的每一个a2,只要在trie树中找一个合法的a1且这个a1的b1最大就行(我们把这个b1加上n2中a2的b2,再在所有b1+b2中取最大值即可
  4. 如何??
  5. 我们把m认为是代价,对于a2的每一位,走与a2相同的边一定不花费代价,走不相同的会花费1<<深度 的代价。
  6. 如果可以走不相同的边,那相同边所对应的那一部分子树一定在m的代价内都能达到,所以直接取max(ans,mx[])。如果可以走不相同的边,那相同边所对应的那一部分子树一定在m的代价内都能达到,所以直接取max(ans,mx[])。
  7. 如果不行,那么递归求解相同的那一部分子树

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


猜你喜欢

转载自blog.csdn.net/qq_42110318/article/details/83628765