【USACO2021 Closest Cow Wins 】题解
题目
Farmer John owns a long farm along the highway that can be considered somewhat
like a one-dimensional number line. Along the farm, there are grassy
patches (); the -th patch is located at position
and has an associated tastiness value ().
Farmer John's nemesis, Farmer Nhoj, has already situated his cows
() at locations . All of these
locations are distinct integers in the range .
Farmer John needs to pick () locations (not
necessarily integers) for his cows to be located. These must be distinct from
those already occupied by the cows of Farmer Nhoj, but it is possible for
Farmer John to place his cows at the same locations as grassy patches.
Whichever farmer owns a cow closest to a grassy patch can claim ownership of
that patch. If there are two cows from rival farmers equally close to the
patch, then Farmer Nhoj claims the patch.
Given the locations of Farmer Nhoj's cows and the locations and tastiness values
of the grassy patches, determine the maximum total tastiness Farmer John's cows
can claim if optimally positioned.
Farmer John 沿着一条高速公路拥有一个很长的农场,可以被看作类似于一维数轴。沿着农场有 K 块草地(1≤K≤2⋅105);第 i 块草地位于位置 pi 并具有美味值 ti(0≤ti≤109)。Farmer John 的死对头 Farmer Nhoj 已经将他的 M 头奶牛(1≤M≤2⋅105)放在了位置 f1…fM 。所有这些 K+M 个位置均是 [0,109] 范围内的不同整数。
Farmer John 需要选择 N
(1≤N≤2⋅105
)个位置(不一定是整数)放置他的奶牛。这些位置必须与 Farmer Nhoj 的奶牛已经占用的位置不同,但是 Farmer John 可以将他的奶牛放在与草地相同的位置。
拥有最靠近某个草地的奶牛的农夫拥有这一草地。如果来自两方农夫的两头奶牛距这一草地相等,则 Farmer Nhoj 拥有该草地。
给定 Farmer Nhoj 的奶牛的位置以及草地的位置和美味值,求 Farmer John 的奶牛以最优方式放置时可以达到的最大总美味值。
思路
考虑在别人的两头奶牛之间放置多少头奶牛。
首先我们可以明确,在FN的任意两头奶牛之间,只能放0/1/2头奶牛。放0头相当于没有,放2头相当于拿走中间所以美味值,难点是放1头。
对于放一头的情况,这头奶牛必然可以且刚好拿到一半的位置,于是我们可以用双指针维护。当这一半位置的左端点移动时,右端点也跟着移动。
最后我们采用一个优先队列来维护。先把所有1头奶牛的情况丢到一个大根堆里,然后每次把1头奶牛pop出去后再把这个区间内2头减1头的数值塞到堆里即可。
总结
对于此类问题,我们可以分区间考虑。对于一些难处理的情况可以采用双指针解决。同时,对于答案可以通过优先队列来维护。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 200010
struct Node
{
int x, y;
bool operator <(const Node &A) const { return x<A.x; }
}t;
struct node { int x, y; }a[N];
int n, m, i, j, k;
priority_queue<Node>q;
int op, opx, s[N], f[N], ans, nw;
int len, nx, nlen, l, r, id;
bool cmp(node x, node y) { return x.x<y.x; }
int findx(int x) {
if(a[n].x<x) return 1e17;
int l=1, r=n, mid;
while(l<r) {
mid=l+r>>1;
if(a[mid].x<x) l=mid+1;
else r=mid;
}
return l;
}
int findy(int x) {
if(a[1].x>x) return -1e17;
int l=1, r=n, mid;
while(l<r) {
mid=l+r+1>>1;
if(a[mid].x<x) l=mid;
else r=mid-1;
}
return l;
}
signed main() {
scanf("%lld%lld%lld", &n, &m, &k);
for(i=1; i<=n; ++i)
scanf("%lld%lld", &a[i].x, &a[i].y), a[i].x*=2;
sort(a+1, a+n+1, cmp);
for(i=1; i<=n; ++i) s[i]=s[i-1]+a[i].y;
for(i=1; i<=m; ++i) scanf("%lld", &f[i]), f[i]*=2;
sort(f+1, f+m+1);
f[0]=-1e17; f[m+1]=1e17;
for(id=0; id<=m; ++id) {
l=findx(f[id]); r=findy(f[id+1]);
if(l>r) continue;
len=f[id+1]-f[id]; nw=0;
for(i=j=l; i<=r; ++i) {
for(; j<=r; ++j)
if((a[j].x-a[i].x)*2>=len) break;
nw=max(nw, s[j-1]-s[i-1]);
}
t.x=nw; t.y=s[r]-s[l-1]-t.x; q.push(t);
}
for(i=1; i<=k; ++i) {
t=q.top(); q.pop();
ans+=t.x; t.x=t.y; t.y=0;
q.push(t);
}
printf("%lld", ans);
return 0;
}
本文来自博客园,作者:zhangtingxi,转载请注明原文链接:https://www.cnblogs.com/zhangtingxi/p/15716487.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战