解题思路:团队成员中必然有一个人限定值最小。因此枚举这个限定值最小的人。
先将所有成员按限定值从大到小排队,然后依次枚举限定值i,枚举时用一个小根堆(优先队列)来存储1...i-1中能力的大值,当枚举到i成员时,根据i成员的限制,将堆中超出限定人数的成员移除出去。那么移除的元素是否后面还会用到呢?因为限定值从大到小,所以i之后的元素限定值会更小,这样就能确定移除不会再被用到。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
struct node
{
int v,s;
bool operator <(const node y)const
{
return v>y.v;
}
} a[100005];
int cmp(node x,node y) //cmp用作排序
{
return x.s>y.s;
}
priority_queue<node>pq;
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
//freopen("5.in","r",stdin);
//freopen("5.out","w",stdout);
int i,j,n;
ll sum=0,maxn=0;
cin>>n;
for(i=1; i<=n; i++)
cin>>a[i].v>>a[i].s;
sort(a+1,a+n+1,cmp);/**< 先按照s排序,先做限制数大的 */
for(i=1; i<=n; i++)
{
pq.push(a[i]);
sum+=a[i].v;/**< 越往后限制越严格,队列存储的一定满足s[i] */
while(pq.size()>a[i].s) /**< 根据s[i],把值最小的踢出去 */
{
sum-=pq.top().v;
pq.pop();
}
maxn=max(maxn,sum);
}
cout<<maxn;
return 0;
}
其实在用优先队列处理数据时不需要存储限定值。只存储能力值即可。下述代码用set取代优先队列。
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
pair<int,int>p[100005];
int main()
{
ios::sync_with_stdio(0);
multiset<int>st;
long long n,i,j,sum=0,ans=0;
cin>>n;
for(i=1;i<=n;i++)
cin>>p[i].second>>p[i].first;
sort(p+1,p+n+1);
for(i=n;i>=1;i--)
{
while(st.size()>=p[i].first)
sum-=*st.begin(),st.erase(st.begin());
sum+=p[i].second;
st.insert(p[i].second);
ans=max(ans,sum);
}
cout<<ans;
return 0;
}