Educational Codeforces Round 61 (Rated for Div. 2) C. Painting the Fence(dp)

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

题意:给出n,m。n指木板长度(1-n),m指m个工人。

接下来给m个区间,表示工人的粉刷范围,求m-2个工人最多粉刷多长的木板。

来自一个大佬博客:http://www.bubuko.com/infodetail-2977901.html

#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<vector>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#define mset(a,b)   memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
//const ll mod=1e9+7;
const int N=1000000;
const int inf=0x3f3f3f3f;
priority_queue<int,vector<int>,greater<int> >q;

int L[5005],dp[5005];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            L[i]=i+1;
            dp[i]=0;
        }
        for(int i=1;i<=m;i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            for(int j=l;j<=r;j++)
            {
                L[j]=min(L[j],l);
                // L[]置为i+1是为了表示没有被画过的状态
            }
        }
        for(int k=1;k<=m-2;k++)
        {
            for(int i=n;i>=1;i--)
            {
                dp[i]=max(dp[L[i]-1]+i-L[i]+1,dp[i]);
                // L[i]~i的一段都被画了 长度为 i-L[i]+1
                // 所以 dp[L[i]-1] 加上 L[i]到i被画的一段 更新dp[i]
            }
            for(int i=1;i<=n;i++)
            {
                dp[i]=max(dp[i],dp[i-1]);
                // 短的段存在更优的方案 自然可以更新长的段
            }
        }
        printf("%d\n",dp[n]);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Kuguotao/article/details/88301227