Educational Codeforces Round 61 C. Painting the Fence

Painting the Fence

time limit per test: 2 second
memory limit per test: 256 megabytes
input: standard input
output: standard output

You have a long fence which consists of n n n sections. Unfortunately, it is not painted, so you decided to hire q q q painters to paint it. i i i-th painter will paint all sections x x x such that l i ≤ x ≤ r i l_i \le x \le r_i lixri.

Unfortunately, you are on a tight budget, so you may hire only q − 2 q - 2 q2 painters. Obviously, only painters you hire will do their work.

You want to maximize the number of painted sections if you choose q − 2 q - 2 q2 painters optimally. A section is considered painted if at least one painter paints it.

Input

The first line contains two integers n n n and q q q ( 3 ≤ n , q ≤ 5000 3 \le n, q \le 5000 3n,q5000) — the number of sections and the number of painters availible for hire, respectively.

Then q q q lines follow, each describing one of the painters: i i i-th line contains two integers l i l_i li and r i r_i ri ( 1 ≤ l i ≤ r i ≤ n 1 \le l_i \le r_i \le n 1lirin).

Output

Print one integer — maximum number of painted sections if you hire q − 2 q - 2 q2 painters.

Example

i n p u t \tt input input
7 5
1 4
4 5
5 6
6 7
3 5
o u t p u t \tt output output
7
i n p u t \tt input input
4 3
1 1
2 2
3 4
o u t p u t \tt output output
2
i n p u t \tt input input
4 4
1 1
2 2
2 3
3 4
o u t p u t \tt output output
3

Tutorial

由题意得, n n n q q q 的范围为 3 ≤ n , q ≤ 5000 3 \le n, q \le 5000 3n,q5000,所以可以用 O ( n 2 ) \mathcal O(n ^ 2) O(n2) 的复杂度解决这个问题

我们可以用一层循环遍历其中一个画家,然后将其画的范围去掉,此时如果去掉第二个画家,只有那些现在被画一次的位置才可能被抹去,此时可以用前缀和计算区间内有多少个这个位置,然后枚举每一个画家,看解雇这个画家后能少画多少位置

此解法时间复杂度为 O ( max ⁡ ( n , q ) 2 ) \mathcal O(\max(n, q) ^ 2) O(max(n,q)2)

Solution

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, q, ans = 0;
    cin >> n >> q;
    vector<int> left(q), right(q), cnt(n + 1), pre(n + 2);
    for (int i = 0; i < q; ++i) {
        cin >> left[i] >> right[i];
        // --left[i], --right[i];
        for (int j = left[i]; j <= right[i]; ++j) {
            cnt[j]++;
        }
    }
    for (int i = 0; i < q; ++i) {
        int l = left[i], r = right[i], count = 0;
        for (int j = l; j <= r; ++j) {
            cnt[j]--;
        }
        for (int j = 0; j <= n; ++j) {
            pre[j + 1] = pre[j];
            if (cnt[j] >= 1) {
                count++;
            }
            pre[j + 1] += cnt[j] == 1;
        }
        for (int j = 0; j < i; ++j) {
            ans = max(ans, count - (pre[right[j] + 1] - pre[left[j]]));
        }
        for (int j = l; j <= r; ++j) {
            cnt[j]++;
        }
    }
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值