题解:P13737 [JOIGST 2025] 茶话会 / Tea Party

题目传送门

题意简述:

现有 \(n\) 块蛋糕分给 \(m\) 个人,另外给每人分一杯茶,如果蛋糕和茶品牌一样则茶的美味度为 \(D\) 否则为 \(0\)。蛋糕的美味度为 \(B\) 且不与其他因素相关,求分完后的美味度最大值。

思路:

可见蛋糕是供大于求,不一定能分完的,所以要有选择的分。分蛋糕时既要考虑其本身的美味度又要考虑能否与茶品牌相同而匹配。

由于茶不会有剩余,因此我们将美味度较高的茶优先与美味度较高的蛋糕匹配,直接修改蛋糕的美味度后对其再进行排序,将蛋糕修改后美味度前 \(n\) 的相加即可。

代码:

#include<bits/stdc++.h>
#define int long long
#define ri register int
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N=200085;

int n,m,x=1,ans;

struct node
{
	int id,v;  // id是品牌编号,v是美味度 
}a[N],b[N];

bool cmp(node u,node v)
{
	if(u.id==v.id)return u.v>v.v; // 同样的品牌优先选美味度高的 
	return u.id<v.id;
}

bool cmpv(node u,node v)
{
	return u.v>v.v;
}

signed main()
{
	ios;cin>>n>>m;
	for(ri i=1;i<=n;i++)
	{
		cin>>a[i].id;
	}
	for(ri i=1;i<=n;i++)
	{
		cin>>a[i].v;
	}
	for(ri i=1;i<=m;i++)
	{
		cin>>b[i].id;
	}
	for(ri i=1;i<=m;i++)
	{
		cin>>b[i].v;
	}
	
	// 依据品牌编号排序,便于修改蛋糕的美味度 
	sort(a+1,a+1+n,cmp);
	sort(b+1,b+1+m,cmp);
	
	// 遍历所有蛋糕,同时用x指针遍历红茶
	for(ri i=1;i<=n&&x<=m;i++)
	{
		if(a[i].id<b[x].id)continue; // 蛋糕<红茶,无法匹配,跳过该蛋糕
		while(x<=m&&a[i].id>b[x].id)x++; // 蛋糕>红茶,移动红茶指针找同品牌
		if(x<=m&&a[i].id==b[x].id)a[i].v+=b[x++].v; //如果相等则进行修改 
	}
	
	// 依据美味度排序,从而求和
	sort(a+1,a+1+n,cmpv);
	
	for(ri i=1;i<=m;i++)
	{
		ans+=a[i].v;
	}
	cout<<ans;
	
	return 0;
}

完结撒花花!

posted @ 2025-10-30 16:16  Circle_Table  阅读(2)  评论(0)    收藏  举报