由题意我们可以得到以下几点:
1.得分方式,我们需要点亮一盏灯,这样我们可以得到点亮这盏灯的分数值bi,很容易想到我们需要在有限的次数里尽可能点亮bi值大的数字。
2:点亮方式:我们要注意到当ai<=x时候这盏灯就会损坏,而x是当前亮着几盏灯,我们可以从这之中得到一个什么新思路呢?就是让数值小的灯放在前面,这样的话就能够点亮尽可能多的灯,从而让我们点亮最多分值。
实现方式:
1:由以上思路我们可以得到,需要以ai为第一关键字排序,bi为第二关键字排序,得到一个优先级序列,我们在每次选择对应段的即未损坏段的最大值,更新到我们的ans中。
2.分段:分段是必需的,为什么呢?因为我们在i=2时候就不能使用i=1的灯了,即我们需要一个关键字key对应相应数值value,这就是一个二维数组或者map(或许么?)
好了,看代码,有很多注释。
#include <bits/stdc++.h>
#define int long long
using namespace std;
bool cmp(auto a,auto b)
{
return a>b;
}
void sol() {
int n;
cin >> n;
vector <pair <int, int> > val(n);//以pair这种类结构体组成一个vector数组,从而得到了两个关键字。
for (int i = 0; i < n; i++) cin >> val[i].first >> val[i].second;
map <int, vector <int> >mp;//一个关键字对应一个vector数组。
int ans = 0;
set <int> st;//内部自动有序且无重复元素的一个stl
for (int i = 0; i < n; i++) {
st.insert(val[i].first);//首先对第一个关键字进行排序。
mp[val[i].first].push_back(val[i].second);//在对应关键字处插入对应的的bi值
}
for (auto c : st) {//遍历set的容器。
sort(mp[c].begin(), mp[c].end(),greater<int>());//对每一段的值都进行排序,从大到小降序排序
}
for (auto c : mp) {
for (int i = 0; i < min((int)c.first, (int)c.second.size()); i++) {
ans += c.second[i];
}
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
sol();
}}