18873 团队实力

18873 团队实力_第1张图片

18873 团队实力_第2张图片

解题思路:团队成员中必然有一个人限定值最小。因此枚举这个限定值最小的人。

先将所有成员按限定值从大到小排队,然后依次枚举限定值i,枚举时用一个小根堆(优先队列)来存储1...i-1中能力的大值,当枚举到i成员时,根据i成员的限制,将堆中超出限定人数的成员移除出去。那么移除的元素是否后面还会用到呢?因为限定值从大到小,所以i之后的元素限定值会更小,这样就能确定移除不会再被用到。

#include 
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_queuepq;
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<

其实在用优先队列处理数据时不需要存储限定值。只存储能力值即可。下述代码用set取代优先队列。

#include 
#include 
#include 
using namespace std;
pairp[100005];
int main()
{
    ios::sync_with_stdio(0);
    multisetst;
    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<