CF2063D Game With Triangles 题解
小清新三分,有几个细节赛时没有调完,遗憾离场,破防了。
注意到如果我们可以求 ,那么 只需要一直枚举 直到 求不出来为止,因此我们直接考虑求 。
我们考虑枚举在 选择三角形的底边数量 ,注意到答案关于 是单峰的。因为如果 不够多,可能 上一些距离较远的点无法被利用,如果 太多了,可能 上一些距离较远的点无法被利用。如果赛时不敢确定可以打个表看看。
考虑如何快速计算。我们可以预处理出来 和 上距离前 大的点两两匹配后得到的贡献,因为我们可以贪心地取这些点对使答案最大。然后取三角形需要另一条线段也贡献一个点,我们判断一下 和 两条线段上用的总点数,如果有一个超了,直接返回负无穷表示不成立。
现在唯一的问题是答案左右两边有一些不成立的位置,如果全部返回负无穷,我们无法确定该舍去哪一段。也就是说,这个函数并不是严格单峰。因此,我们在负无穷上面加上一些东西,使得答案变成严格单峰。具体的,我们可以通过使其不成立的条件判断出来是左边的不成立还是右边的不成立,如果是左边的不成立,那么返回负无穷加上 ,否则返回负无穷加上 。
还有一些坑点,重复地元素需要特判,以及三分遇到相等的点应该舍左边而不是舍右边。
#include <bits/stdc++.h>
using namespace std;
long long t,n,m,a[300000],b[300000],pa[300000],pb[300000],ou[300000];
long long check(long long x,long long k)
{
if((x*2+k-x)>n||pa[x]==-1e18)return -(long long)1e18+k-x;
if((x+(k-x)*2)>m||pb[k-x]==-1e18)return -(long long)1e18+x;
return pa[x]+pb[k-x];
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=m;i++)scanf("%lld",&b[i]);
sort(a+1,a+n+1),sort(b+1,b+m+1);
for(int i=1;i<=max(m,n);i++)pa[i]=pb[i]=-1e18;
for(int i=1;i<n-i+1;i++)
if(a[n-i+1]!=a[i])pa[i]=pa[i-1]+a[n-i+1]-a[i];
else break;
for(int i=1;i<m-i+1;i++)
if(b[m-i+1]!=b[i])pb[i]=pb[i-1]+b[m-i+1]-b[i];
else break;
long long flag=0;
for(int i=1;i<=max(m,n);i++)
{
long long l=0,r=i,ans=-1e18;
while(l<=r)
{
long long lmid=(l*2+r)/3,rmid=(l+r*2)/3;
if(check(lmid,i)>check(rmid,i))ans=max(ans,check(lmid,i)),r=rmid-1;
else ans=max(ans,check(rmid,i)),l=lmid+1;
}
ou[i]=ans;
if(ou[i]<0)
{
printf("%d\n",i-1),flag=i-1;
for(int j=1;j<=i-1;j++)printf("%lld ",ou[j]);
break;
}
}
if(flag)printf("\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探