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−2painters.
Examples
7 5 1 4 4 5 5 6 6 7 3 5
7
4 3 1 1 2 2 3 4
2
4 4 1 1 2 2 2 3 3 4
3
解题过程:
遍历一下每个栅栏有多少人会在这里刷漆,对于在漆工范围内的栅栏存储总量。用前缀和数组记录刷一次和刷两次的位置。
暴力寻找哪两个漆工去掉后会让栅栏不能刷漆,取最小值。用总量-最小值。大牛只需要分三种情况,在下天资愚钝,分了6种情况。
第一种:
.........................
.........................
第二种:
.......................
..............................
第三种:
.........................
..............
第四种:
.........................
..................
第五种:
.........................
...........................
第六种:
.............
............
上代码:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<string> #include<vector> #include<iostream> #include<cstring> #define inf 0x3f3f3f3f using namespace std; #define ll long long struct node { int l; int r; int idx; }; int x,y; node a[5005]; int t[5005]; int one[5005]; int two[5005];///前缀和数组 bool cmp(node p1,node p2) { if(p1.l==p2.l) return p1.r<p2.r; else return p1.l<p2.l; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { memset(a,0,sizeof(a)); memset(t,0,sizeof(t)); for(int i=0;i<m;i++) { scanf("%d%d",&a[i].l,&a[i].r); for(int j=a[i].l;j<=a[i].r;j++) t[j]++; } int ans=0,minn=inf; for(int i=1;i<=n;i++) { if(t[i]) { ans++; } one[i]=one[i-1]+(t[i]==1);///前缀和赋值不能放括号里面 two[i]=two[i-1]+(t[i]==2);///前缀和需要连续赋值,如果if不成功则不赋值,造成中断 } sort(a,a+m,cmp); for(int i=0;i<m;i++)///hello { for(int j=i+1;j<m;j++)///下标j在i后面,j的l始终大于等于i的l { if( a[i].l==a[j].l && a[i].r==a[j].r)///1 minn=min(minn,( two[ a[i].r ]-two[ a[i].l-1 ] ) ); else if(a[i].l==a[j].l && a[i].r<a[j].r)///2 minn=min(minn,( two[ a[i].r ]-two[ a[i].l-1 ] ) + ( one[ a[j].r ]-one[ a[i].r ] ) ); else if( a[i].r>a[j].r )///3 minn=min(minn,( one[ a[j].l-1 ]-one[ a[i].l-1 ] ) + ( two[ a[j].r ]-two[ a[j].l-1 ] ) + ( one[ a[i].r ]-one[ a[j].r ]) ); else if( a[i].r==a[j].r )///4 minn=min(minn,( one[ a[j].l-1 ]-one[ a[i].l-1 ] ) + ( two[ a[j].r ]-two[ a[j].l-1 ] ) ); else if( a[i].r<a[j].r && a[i].r>=a[j].l )///5 minn=min(minn,( one[ a[j].l-1 ]-one[ a[i].l-1 ] ) + ( two[ a[i].r ]-two[ a[j].l-1 ] ) + ( one[ a[j].r ]-one[ a[i].r ]) ); else if( a[i].r<a[j].l )///6 minn=min(minn,( one[ a[i].r ]-one[ a[i].l-1 ] ) + ( one[ a[j].r ]-one[ a[j].l-1 ] ) ); } } printf("%d ",ans-minn); } return 0; }