题意:有一排长度为 n 的栅栏需要涂油漆,现在有 q 个油漆工,每个人可以涂一段连续的栅栏,但是你只能最多聘用 q-2 个油漆工,求最多能涂的栅栏数;
分析:因为 n,q<=5000 范围比较小,则可以枚举 q-1 个油漆工能覆盖的区域,再在这 q-1 个油漆工覆盖的区域中找出并标记栅栏只被涂过一次的地方(即这个栅栏只由q-1个油漆工的其中一个涂),做前缀和,再枚举q-1个油漆工的工作区域,然后更新答案;
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 5005;
int l[N],r[N],cnt[N],pre[N];
int n,q;
int sum,ans;
int main()
{
ans=0;
cin>>n>>q;
for(int i=1;i<=q;i++)
{
cin>>l[i]>>r[i];
for(int j=l[i];j<=r[i];j++) cnt[j]++;
}
for(int i=1;i<=q;i++)
{
for(int j=l[i];j<=r[i];j++) cnt[j]--; //枚举去掉一个油漆工的贡献
sum=0;
for(int j=1;j<=n;j++)
{
if(cnt[j]==1) //=1表示这个栅栏只由一个油漆工控制
pre[j]=pre[j-1]+1; //做前缀和
else
pre[j]=pre[j-1];
if(cnt[j]) //统计q-1个油漆工一共刷了几块栅栏
sum++;
}
for(int j=i+1;j<=q;j++)
ans=max(ans,sum-pre[r[j]]+pre[l[j]-1]);
for(int j=l[i];j<=r[i];j++) cnt[j]++;
}
cout<<ans<<endl;
return 0;
}