1132C - Painting the Fence(思维+差分)

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/115201806