https://codeforces.com/problemset/problem/1132/C
思路:可以发现n^2枚举。
对于去除第一个人后序列的状态,可以O1用差分修改出来。然后On累加。
去除第二个人后序列的答案怎么算。可以发现去除第二个人后对其所在的[l,r]区间内还剩涂了一次的状态去除掉就好了。所以前缀和统计一下只有一个覆盖情况的。
差分维护好扫一遍处理好前缀,然后On枚举。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=5e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
struct P{
LL l,r;
}a[maxn];
LL cnt[maxn];///差分数组
LL pre[maxn];
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,q;cin>>n>>q;
for(LL i=1;i<=q;i++){
cin>>a[i].l>>a[i].r;
cnt[a[i].l]++;cnt[a[i].r+1]--;
}
LL ans=0;
for(LL i=1;i<=q;i++){///枚举去掉第一个人的序列状态
cnt[a[i].l]--;cnt[a[i].r+1]++;
LL tmp=0;LL res=0;
memset(pre,0,sizeof(pre));
for(LL j=1;j<=n;j++){
res+=cnt[j];
if(res>0) tmp++;
if(res==1) pre[j]=pre[j-1]+1;
else pre[j]=pre[j-1];
}
for(LL j=1;j<=q;j++){
if(i==j) continue;
ans=max(ans,tmp-(pre[a[j].r]-pre[a[j].l-1]));
}
cnt[a[i].l]++;cnt[a[i].r+1]--;
}
cout<<ans<<"\n";
return 0;
}