首先,如果选择
个粒子,那么这
个粒子都需要满足
,即
如果选取商店里的粒子
,假设一共选择了
个粒子,那么需要满足
,其余了
个粒子都需要满足
,那么此时能量的最大值为
定义
表示原始粒子中所有满足
的前
大粒子的能量和
-
如果
的粒子数小于
,那么就是这全部粒子的能量和
-
如果
的粒子数大于等于
,那么取前
大粒子的能量和
如何求
:
将
从
到
按照从大到小的顺序遍历,这样满足已经放入的粒子仍然满足
,现在需要维护前
大的粒子能量和最大值,所以用优先队列模拟
使用小根堆,这样先
进去,如果堆里面的元素数量多了,再取出堆顶最小的几个元素
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;
priority_queue<int, vector<int>, greater<int> > q;
void solve(){
while(q.size()) q.pop();
int n, m; cin >> n >> m;
vector<vector<int> > adj(n + 10);
for(int i = 1; i <= n; i ++){
int x, y; cin >> x >> y;
adj[y].push_back(x);
}
vector<int> a(n + 10);
a[0] = 0;
int sum = 0, ans = 0;
for(int i = n; i >= 1; i --){
for(int x : adj[i]){
q.push(x);
sum += x;
}
while((int)q.size() > i){
sum -= q.top();
q.pop();
}
a[i] = sum;
}
while(q.size()) q.pop();
sum = 0;
for(int i = n; i >= 0; i --){
for(int x : adj[i]){
sum += x;
q.push(x);
}
while((int)q.size() > i + 1){
sum -= q.top();
q.pop();
}
ans = max(ans, sum);
}
vector<int> pre(n + 10);
for(int i = 1; i <= n; i ++) pre[i] = max(pre[i - 1], a[i]);
for(int i = 1; i <= m; i ++){
int x, y; cin >> x >> y;
cout << max(ans, x + pre[y]) << " ";
}
cout << endl;
return ;
}
signed main(){
HelloWorld;
int tt = 1;
cin >> tt;
while(tt --) solve();
return 0;
}



京公网安备 11010502036488号