Educational Codeforces Round 61 (Rated for Div. 2)(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

题意就是找q-2个区间使得尽量覆盖n区间的长度。

别人的代码加自己的注释:

先把所有区间内都加上1,然后枚举两个区间,把这两个区间内减1,统计0的个数

反过来求,找两个区间,假设去掉这两个区间,求剩下的区间能覆盖的长度。维护最大值即可。

问题一:那么如何求 “剩下的区间能覆盖的长度” ?

解决问题一:

先假设求一个区间:假设去掉这一个区间,剩下的q-1个区间能覆盖的最大区间。

先给一个前提:把每个画匠能画的区间全部加上一:

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

那么预处理数组a为1 1 2 3 3 2 1

枚举1 4,去掉1 4则将a数组内1到4全部减一:0 0 1 2 3 2 1,0的个数就是不能覆盖的区间,剩下的q-1个区间能覆盖的区间为7-2=5;

统计0的个数直接用sum[i][1]

保存a数组中的1的前缀和就可以了。1就是只被一个区间覆盖

用sum[r][1]-sum[l-1][0]可O(1)求0的个数

这里的sum【1】应为1 2 2 2 2 2 3

问题二:如何求去掉两个区间后,剩下的区间能覆盖的长度?

解决问题二:

如果两个区间没有交叉,那么就当作两个去掉一个区间处理,

就是解决问题一提到的方法。

如果两个区间有交叉。将交叉的地方特殊处理,

不交叉的地方当作一个区间处理。

将交叉的地方特殊处理:

保存a数组中的2的前缀和就可以了。

然后将sum[r][2]-sum[l-1][2],就是0的个数(不能被覆盖的个数)。

因为如果a数组中为3,那就是三个区间交叉,无论去掉哪两个,这个3区间还是能被覆盖。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
int l[maxn],r[maxn],a[maxn],n,ans,res;
int sum[maxn][4];
int main()
{
	int q;
	scanf("%d%d",&n,&q);
	for(int i=1;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];//求前缀和 
		if(a[i])res++;//res是能被覆盖总区间 
		//维护a中1的前缀和 和2的前缀和 
		for(int j=0;j<3;j++)
		sum[i][j]=sum[i-1][j];
		if(a[i]==1)sum[i][1]++;
		if(a[i]==2)sum[i][2]++;
	}
	for(int i=1;i<q;i++)//枚举两个区间 求两个区间不能被覆盖的最小值t
	for(int j=i+1;j<=q;j++)
	{
		int ql=max(l[i],l[j]);
		int qr=min(r[i],r[j]);
		if(ql>qr)//无重叠 
		{
			int t=sum[r[i]][1]-sum[l[i]-1][1];
			t+=sum[r[j]][1]-sum[l[j]-1][1];
			ans=max(ans,res-t);
		}
		else//有重叠 
		{
			int t=sum[qr][2]-sum[ql-1][2];//重叠部分 
			int ll=min(l[i],l[j]);
			int rr=max(r[i],r[j]);
			t+=sum[ql][1]-sum[ll-1][1];//非重叠部分 
			t+=sum[rr][1]-sum[qr][1];
			ans=max(ans,res-t);
		}
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/88309860