【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 \(K\) grassy
patches (\(1 \leq K \leq 2\cdot 10^5\)); the \(i\)-th patch is located at position
\(p_i\) and has an associated tastiness value \(t_i\) (\(0\le t_i\le 10^9\)).
Farmer John's nemesis, Farmer Nhoj, has already situated his \(M\) cows
(\(1 \leq M \leq 2\cdot 10^5\)) at locations \(f_1 \ldots f_M\). All \(K+M\) of these
locations are distinct integers in the range \([0,10^9]\).

Farmer John needs to pick \(N\) (\(1\le N\le 2\cdot 10^5\)) 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;
}
posted @ 2021-12-21 18:10  zhangtingxi  阅读(524)  评论(0编辑  收藏  举报