CF1132C:Painting the Fence(暴力)

C. Painting the Fence

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You have a long fence which consists of nn sections. Unfortunately, it is not painted, so you decided to hire qq painters to paint it. ii-th painter will paint all sections xx such that li≤x≤rili≤x≤ri.

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

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

Input

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

Then qq lines follow, each describing one of the painters: ii-th line contains two integers lili and riri (1≤li≤ri≤n1≤li≤ri≤n).

Output

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

Examples

input

Copy

7 5
1 4
4 5
5 6
6 7
3 5

output

Copy

7

input

Copy

4 3
1 1
2 2
3 4

output

Copy

2

input

Copy

4 4
1 1
2 2
2 3
3 4

output

Copy

3

题意:给Q个线段,要去掉两条,剩下的线段覆盖总长度最长。

思路:Q的范围允许O(n*n)复杂度,先预处理每个格子被覆盖非0次,被覆盖1次,被覆盖2次的情况,再暴力枚举去掉哪两条就ok,假如去掉X和Y两条,那么覆盖数量减少为X\capY部分的覆盖2次的格子数加上X xor Y部分的覆盖1次的格子数,这些通过前缀和方便求出来。

# include <bits/stdc++.h>
using namespace std;
const int N = 6e3;
int l[N], r[N], a[N];
int one[N], two[N];
int fun(int x, int y){
    int s1 = 0, s2 = 0;
    if(l[x] > l[y]) swap(x, y);
    int tmp = min(l[y], r[x]);
    s1 += one[tmp]-one[l[x]-1];
    tmp = min(r[x], r[y]);
    s2 += max(0, two[tmp]-two[l[y]-1]);

    if(r[x] < r[y]) swap(x, y);
    tmp = max(l[x], r[y]);
    s1 += one[r[x]]-one[tmp-1];
    return s1+s2;
}
int main(){
    int n, q, sum = 0;
    scanf("%d%d",&n,&q);
    for(int i=0; i<q; ++i){
        scanf("%d%d",&l[i], &r[i]);
        ++a[l[i]];
        --a[r[i]+1];
    }
    for(int i=1; i<=n; ++i){
        a[i] += a[i-1];
        one[i] = one[i-1];
        two[i] = two[i-1];
        if(a[i] > 0) ++sum;
        if(a[i] == 1) ++one[i];
        else if(a[i] == 2) ++two[i];
    }
    int ans = 0;
    for(int i=0; i<q; ++i){
        for(int j=0; j<q; ++j){
            if(i == j) continue;
            int tmp = fun(i,j);
            ans = max(ans, sum-tmp);
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值