题解:P10277 [USACO24OPEN] Bessie's Interview S
第一个问题比较简单,只需要用优先队列模拟,里面存下当前每个农夫面试的奶牛的结束面试的时间即可,最后输出 q.top()。
重点在第二问。好像很多题解没说清楚为什么不能用并查集,这里举出一个例子:
输入:
8 3
4 4 5 1 2 3 4 1
它对应的农夫每个时刻面试的奶牛编号是这样的:
1 2 3
1 2 3
1 2 3
1 2 3
4 5 3
6 5 7
6 8 7
6 . 7
. . 7
在第
在第
而如果使用并查集,在第
那么正确的解法应该是什么呢?
拿优先队列跑过一遍后,我们可以在中途存下每个奶牛开始面试和结束面试的时间。这个值是确定的,即使面试这些奶牛的农夫可能不确定。首先拿 Bessie 开始面试的时间找到结束面试的时间为这个值的奶牛,这些奶牛是有可能在此时让 Bessie 排到后面的。继续拿这些奶牛的开始时间找结束时间相同的奶牛,最终直到找到了编号在
具体实现时,注意到拿第 set 维护当前需要找结束时间为多少的奶牛。遍历到一个奶牛时,如果这个奶牛的结束时间正好是我们要找的,那么就把它的开始时间放到 set 里面。如果 bool 数组标记一下即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[300005],st[300005],ed[300005];
priority_queue<int,vector<int>,greater<int>>q;
set<int>s;
bool b[300005];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=k;i++){
ed[i]=a[i];
q.push(ed[i]);
}
for(int i=k+1;i<=n;i++){
int x=q.top();q.pop();
st[i]=x;ed[i]=x+a[i];
q.push(ed[i]);
}
cout<<q.top()<<endl;
s.insert(q.top());
for(int i=n;i>=1;i--){
if(s.find(ed[i])!=s.end()){
s.insert(st[i]);
if(i<=k)b[i]=1;
}
}
for(int i=1;i<=k;i++)cout<<b[i];
return 0;
}