cf1061D TV shows

题意:

把 n 个区间分成任意组,组内区间两两不交。每组的花费为 \(x+y(\)组中最右右端点-最左左端点\()\) 。求最小花费

思路:

非常草率的证明:

把区间按左端点排序。对于当前区间 \(i\) 和后面的某个区间 \(j\) ,假设前面有俩区间甲和乙,甲的右端点小于乙的右端点。有几种决策:

  1. \(i\) 与乙一组,\(j\) 与甲一组
  2. \(i\) 与甲一组,\(j\) 与乙一组
  3. \(i\) 与乙一组,\(j\) 新开一组
  4. \(i\) 新开一组,\(j\) 与乙一组

3和4对后续的影响一样,但3比较便宜。

1和2的花费是一样的,对后续其他区间的影响也一样。选1好一点。

唉反正对于每个区间,应该尝试接到一个前面的右端点最大的区间。接上去不如新开一组的话就新开

const signed N = 1e5 + 3, mod = 1e9 + 7;
ll n, x, y, ans;
PLL a[N];
 
signed main() {
    iofast;
    cin >> n >> x >> y;
    for(int i = 1; i <= n; i++) cin >> a[i].fi >> a[i].se;
    sort(a + 1, a + 1 + n);
 
    priority_queue<ll, vector<ll>, greater<ll>> p; //备选r池
    priority_queue<ll> q; //能选r池
    for(int i = 1; i <= n; i++) {
        ans += y*(a[i].se-a[i].fi) % mod;
        while(p.size() && p.top() < a[i].fi) q.push(p.top()), p.pop();
        if(q.size() && y*(a[i].fi-q.top())<x)
            ans += y*(a[i].fi-q.top()) % mod, q.pop();
        else ans += x;
        p.push(a[i].se);
    }
    cout << ans % mod;
}
posted @ 2022-04-25 13:58  Bellala  阅读(25)  评论(0)    收藏  举报