牛客网【每日一题】3月25
题号:NC50439
名称: tokitsukaze and Soldier
来源:练习赛50-C
链接: link.
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
在一个游戏中,tokitsukaze需要在n个士兵中选出一些士兵组成一个团去打副本。
第i个士兵的战力为v[i],团的战力是团内所有士兵的战力之和。
但是这些士兵有特殊的要求:如果选了第i个士兵,这个士兵希望团的人数不超过s[i]。(如果不选第i个士兵,就没有这个限制。)
tokitsukaze想知道,团的战力最大为多少。
输入描述:
第一行包含一个正整数n(1≤n≤10^5)。
接下来n行,每行包括2个正整数v,s(1≤v≤10^9,1≤s≤n)。
输出描述:
输出一个正整数,表示团的最大战力。
示例1
输入
2
1 2
2 2
输出
3
示例2
输入
3
1 3
2 3
100 1
输出
100
思路
所求的最大战斗力由v和s这两个因素限制。
结构体数组a存放v和s,然后对其排序,先按照s从大到小,如果s相同再排v,也是从大到小(先要保证足够的人数,后面好进行取舍)。
定义一个从小到大的优先队列q,ans相互跟随q,(q每次添加一个战力值,同时用ans加上战力值;ans删去,q也弹出),战力值的先后加入由s的排序决定,当q的元素数量大于当前s的值时(s是由大到小的排序的),就将多出的部分pop出(q是从小到大排序,所以弹出的总是其中最小值),再用ans减去,这样ans的值即为在人数限定在s内的最佳情况(因为弹出的是最小值,相对于前s个数的和,所以之后也不用再考虑被弹出的数),记录ans的最大值
我刚开始提交是70多分,想了一阵子才发现是数组开小了(笑哭)
#include<map>
#include<queue>
#include<bits/stdc++.h>
#define maxn 100004
using namespace std;
struct node{
long long int v,s;
};
node a[maxn];
bool cmp(node a,node b)
{
if(a.s!=b.s)return a.s>b.s;
else return a.v>a.v;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].v>>a[i].s;
}
sort (a+1,a+1+n,cmp);
// int tot=0;
long long int ans=0;
int minn=maxn;
long long int maxx=0;
priority_queue<int,vector<int>,greater<int> >q;
for(int i=1;i<=n;i++)
{
q.push(a[i].v);
ans+=a[i].v;
while(q.size()>a[i].s)
{
ans-=q.top();
// printf("q.size=%d,a[i].s=%d,ans=%d\n",q.size(),a[i].s,ans);
q.pop();
// tot--;
}
if(ans>maxx)maxx=ans;
}
cout<<maxx;
return 0;
}