【牛客练习赛50】 tokitsukaze and Soldier
题目描述
在一个游戏中,tokitsukaze需要在 n个士兵中选出一些士兵组成一个团去打副本。
第i个士兵的战力为 v[i],团的战力是团内所有士兵的战力之和。
但是这些士兵有特殊的要求:如果选了第 i个士兵,这个士兵希望团的人数不超过 s[i]。(如果不选第i个士兵,就没有这个限制。)
tokitsukaze想知道,团的战力最大为多少。
输入描述:
第一行包含一个正整数 n( 1≤n≤105)。
接下来 n行,每行包括2个正整数 v,s ( 1≤v≤109,1≤s≤n)。
输出描述:
输出一个正整数,表示团的最大战力。
示例1
输入
2
1 2
2 2
输出
3
示例2
输入
3
1 3
2 3
100 1
输出
100
Solution
数据范围目测是 O(nlogn)马上想到堆
一个显而易见的算法
for i = 1 to n
ans = max(ans, v[i] + 从所有满足s[j] >= s[i]且i != j的j中选<= s[i] - 1个的v[j]的最大和)
按s[i]降序排序后考虑用堆去维护决策集合
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e5 + 10;
int n;
long long t = 0, ans = 0;
struct soldier
{
int v, s;
} a[N];
bool cmp(soldier a, soldier b) { return a.s > b.s; }
priority_queue<int, vector<int>, greater<int> > q;
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &a[i].v, &a[i].s);
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
while (q.size() >= a[i].s)
{
t -= q.top();
q.pop();
}
ans = max(ans, t + a[i].v);
q.push(a[i].v);
t += a[i].v;
}
printf("%lld", ans);
return 0;
}