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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM