法一:线段树维护区间最小值,每次选尽可能用优惠券后的价格最小的物品,然后将该物品价格修改为无穷大(单点修改),将使用过的优惠券的影响消除(区间修改)
#include<bits/stdc++.h>
using namespace std;
#define lson p << 1
#define rson p << 1 | 1
#define int long long
const int maxn = 2e5 + 5, inf = 1e9 + 5;
int t[maxn << 2], lazy[maxn << 2], d[maxn], a[maxn], r[maxn], w[maxn];
struct Node{
int r, w;
bool operator < (const Node &x)const{
return r < x.r;
}
}b[maxn];
void push_up(int p){
t[p] = min(t[lson], t[rson]);
}
void push_down(int p){
lazy[lson] += lazy[p];
lazy[rson] += lazy[p];
t[lson] += lazy[p];
t[rson] += lazy[p];
lazy[p] = 0;
}
void build(int p, int l, int r){
if(l == r){
t[p] = a[l];
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
push_up(p);
}
pair<int, int> query(int p, int l, int r){
if(l == r){
int tmp = t[p];
t[p] = inf;
//push_up(p);不用push_up!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return {l, tmp};
}
int mid = (l + r) >> 1;
pair<int, int> res;
push_down(p);
if(t[lson] < t[rson]) res = query(lson, l, mid);
else res = query(rson, mid + 1, r);
push_up(p);
return res;
}
void update(int p, int l, int r, int L, int R, int val){
if(L <= l && R >= r){
t[p] += val;
lazy[p] += val;
//push_up(p);不用push_up!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return;
}
push_down(p);
int mid = (l + r) >> 1;
if(L <= mid) update(lson, l, mid, L, R, val);
if(R >= mid + 1) update(rson, mid + 1, r, L, R, val);
push_up(p);
}
void solve(){
int n, m, i, j;
cin >> n >> m;
for(i = 1; i <= n; i++){
cin >> a[i];
d[i] = 0;
//cout << a[i] << ' ';
}
//cout << '\n';
for(i = 1; i <= 4 * n; i++){
lazy[i] = 0;
}
for(i = 1; i <= m; i++){
cin >> b[i].r >> b[i].w;
d[1] -= b[i].w;
d[b[i].r + 1] += b[i].w;
}
int sum = 0;
for(i = 1; i <= n; i++){
sum += d[i];
a[i] = a[i] + sum;
//cout << a[i] << ' ';
}
sort(b + 1, b + m + 1);
build(1, 1, n);
//cout << 8 << ' ' << t[8] << '\n';
int now = 0;
for(int k = 1; k <= n; k++){
auto pr = query(1, 1, n);
now += pr.second;
cout << now << ' ';
int pos = pr.first;
int p = lower_bound(b + 1, b + m + 1, Node{pos, 0}) - b;
//cout << k << ' ' << pos << ' ' << p << ' ' << m << '\n';
//cout << k << ' ';
// for(i = 1; i <= 9; i++){
// cout << t[i] << ' ';
// }
// cout << '\n';
for(i = p; i <= m; i++){
update(1, 1, n, 1, b[i].r, b[i].w);
}
m = p - 1;
}
cout << '\n';
}
//struct ti
//{
// int w, r;
//}tic[maxn];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
while(T--)
solve();
}
法二:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS \
ios::sync_with_stdio(0); \
cin.tie(0);
#define PII pair<int, int>
#define maxn 200010
int a[maxn];
PII ask[maxn];
signed main(void)
{
IOS int t;
cin >> t;
while (t--)
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= m; i++)
{
cin >> ask[i].first >> ask[i].second;
}
sort(ask + 1, ask + 1 + m);
int it = 0;
multiset<int> st;
for (int i = 1; i <= m; i++)
{
while (it < ask[i].first)
{
st.insert(a[++it]);
}
int x = *st.begin();
st.erase(st.begin());
x -= ask[i].second;
st.insert(x);
}
while (it < n)
st.insert(a[++it]);
int res = 0;
// cout<<st.size()<<endl;
for (auto &x : st)
{
res += x;
cout << res << " ";
}
cout << endl;
}
return 0;
}