Luogu P7913 [CSP-S 2021] 廊桥分配 题解 [ 绿 ] [ 贪心 ] [ 前缀和 ] [ STL ]

廊桥分配

笑点解析:VP 的时候想这题想了 20min,比想 T3 的时间长。

关键结论:在不考虑廊桥限制的情况下,给每个飞机分配一个最小的廊桥编号。当最终廊桥数目大于等于其对应编号时,飞机才能被分配到廊桥。

理解起来比较简单,首先有一个结论:一旦一架飞机被分到了廊桥,那么对于更多数目的廊桥,他也一定会被分到。我们假设向一个方案中再加一个廊桥,那么新加入的被分到廊桥的飞机就一定是最小编号等于当前廊桥数目的飞机。这些暂未被分到廊桥的飞机就相当于停在了远机位。

因此将所有区间按 \(l, r\) 双关键字排序后,对每个区域求出每架飞机的最小的廊桥编号。这个可以用 set 维护最小编号,用 priority_queue 维护删除的时间。最后求出最小编号后对廊桥的值域做前缀和,最后枚举两部分廊桥的数目即可。

时间复杂度 \(O(n\log n)\),结论比较简单,但是这也太 Ad-hoc 了。

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
using pi = pair<int, int>;
const int N = 100005;
set<int> s;
priority_queue<pi, vector<pi>, greater<pi> > q;
int n, ma, mb, f[N], g[N], lva[N], lvb[N], ans;
pi a[N], b[N];
int main()
{
    // freopen("airport.in", "r", stdin);
    // freopen("airport.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> ma >> mb;
    for(int i = 1; i <= ma; i++) cin >> a[i].fi >> a[i].se;
    for(int i = 1; i <= mb; i++) cin >> b[i].fi >> b[i].se;
    sort(a + 1, a + ma + 1);
    sort(b + 1, b + mb + 1);
    for(int i = 1; i <= ma + 1; i++) s.insert(i);
    for(int i = 1; i <= ma; i++)
    {
        int l = a[i].fi, r = a[i].se;
        while(!q.empty() && q.top().fi < l)
        {
            int id = q.top().se;
            s.insert(id);
            q.pop();
        }
        lva[i] = (*s.begin());
        s.erase(lva[i]);
        f[lva[i]]++;
        q.push({r, lva[i]});
    }
    while(!q.empty()) q.pop();
    s.clear();
    for(int i = 1; i <= mb + 1; i++) s.insert(i);
    for(int i = 1; i <= mb; i++)
    {
        int l = b[i].fi, r = b[i].se;
        while(!q.empty() && q.top().fi < l)
        {
            int id = q.top().se;
            s.insert(id);
            q.pop();
        }
        lvb[i] = (*s.begin());
        s.erase(lvb[i]);
        g[lvb[i]]++;
        q.push({r, lvb[i]});
    }    
    for(int i = 1; i <= n + 1; i++) f[i] += f[i - 1];
    for(int i = 1; i <= n + 1; i++) g[i] += g[i - 1];
    for(int i = 0; i <= n; i++) ans = max(ans, f[i] + g[n - i]);
    cout << ans;
    return 0;
}
posted @ 2025-10-28 19:31  KS_Fszha  阅读(5)  评论(0)    收藏  举报