P16858 [GKS 2021 #F] Festival 题解

题目

Solution

思路

我们可以使用扫描线的思想来解决。存储在第 \(i\) 天开始的活动和结束的活动。

我们注意到 \(D \le 3 \times 10^5\) 所以不用离散化。可以扫描每一天的开始的活动和结束的活动,并维护前 \(K\) 大的快乐值之和。考虑使用对顶堆:通过一个大根堆 \(q_1\) 和小根堆 \(q_2\) 可以维护前 \(K\) 大和剩余的部分,稍加改装,维护一个 \(size\)\(sum\),在加入时顺便更新,就可以维护总和。

可是堆的任意删除是 \(O(n)\) 复杂度的,所以我们可以引入懒标记。注意到 \(h_i\) 可以重复,所以 \(lsy_{h_i}\) 标记的应该是 \(h_i\) 要删除的个数。

我们注意到删除时需要优先删除下面那个堆,所以要分类讨论。

if(h >= q2.top()) {
    if(q2.top() == h && (q1.empty() ? 1 : q1.top() < h)) q2sz--, q2cnt -= h, lsy2[h]++;
    else if(q2.top() == h && q1.top() == h) q1sz--, q1cnt -= h, lsy1[h]++;
    else if(q2.top() < h) q2sz--, q2cnt -= h, lsy2[h]++;
}
else q1sz--, q1cnt -= h, lsy1[h]++;

为了不删错堆,可以分成两个懒标记数组,分别存上面的堆和下面的堆。然后就可以统计了。

注意:记得开long long

我也不知道我怎么过去的,有更好的写法在评论区指正。

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 3e5 + 5;
ll lsy1[N], lsy2[N];
priority_queue<ll> q1;
priority_queue<ll, vector<ll>, greater<ll>> q2;
ll q1sz, q2sz, q1cnt, q2cnt;
ll d, n, k;
void ph() {
    while(q2sz != k) {
        if(q2sz < k) {
            while(!q1.empty() && lsy1[q1.top()]) lsy1[q1.top()]--, q1.pop();
            if(!q1.empty()) {
                q2.push(q1.top());
                q2cnt += q1.top(), q1cnt -= q1.top();
                q1.pop();
                q2sz++, q1sz--;
            }
        }
        if(q2sz > k) {
            while(!q2.empty() && lsy2[q2.top()]) lsy2[q2.top()]--, q2.pop();
            if(!q2.empty()) {
                q1.push(q2.top());
                q2cnt -= q2.top(), q1cnt += q2.top();
                q2.pop();
                q1sz++, q2sz--;
            }
        }
        if(q1sz == 0 && q2sz <= k) break;
    }
}
void add(ll h) {
    q2.push(h), q2sz++, q2cnt += h;
    ph();
}
void del(ll h) {
    while(!q1.empty() && lsy1[q1.top()]) lsy1[q1.top()]--, q1.pop();
    while(!q2.empty() && lsy2[q2.top()]) lsy2[q2.top()]--, q2.pop();
    if(h >= q2.top()) {
        if(q2.top() == h && (q1.empty() ? 1 : q1.top() < h)) q2sz--, q2cnt -= h, lsy2[h]++;
        else if(q2.top() == h && q1.top() == h) q1sz--, q1cnt -= h, lsy1[h]++;
        else if(q2.top() < h) q2sz--, q2cnt -= h, lsy2[h]++;
    }
    else q1sz--, q1cnt -= h, lsy1[h]++;
    ph();
}
int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    ll T; cin >> T;
    for(ll t = 1; t <= T; t++) {
        memset(lsy1, 0, sizeof(lsy1));
        memset(lsy2, 0, sizeof(lsy2));
        q1 = priority_queue<ll>();
        q2 = priority_queue<ll, vector<ll>, greater<ll>>();
        q1sz = q2sz = q1cnt = q2cnt = 0;
        cin >> d >> n >> k;
        vector<vector<ll>> p(d + 2), q(d + 2);
        ll ans = 0;
        for(ll i = 1, s, e, h; i <= n && cin >> h >> s >> e; i++) {
            p[s].push_back(h), q[e + 1].push_back(h);
        }
        for(ll i = 1; i <= d; i++) {
            for(auto h : p[i]) add(h);
            for(auto h : q[i]) del(h);
            ans = max(ans, q2cnt);
        }
        cout << "Case #" << t << ": " << ans << "\n";
    }
    return 0;
}
posted @ 2026-07-22 21:18  deepsleep  阅读(11)  评论(0)    收藏  举报