题目大意:现在有n个栅栏板,p个工人,每个工人可以涂一段区间的栅栏板,问如果雇佣p-2个工人,最多可以涂多少块栅栏板。
做法:先求出q个工人能涂得最多木板数,并统计每个木板被涂的次数。求被涂一次的木板个数和被涂两次的木板个数的前缀和。
暴力枚举选择去掉哪两个工人,并且看看能删掉几个木板。即可
#include<iostream> #include<cstdio> #define maxn 5010 using namespace std; int n,p,l[maxn],r[maxn],a[maxn],sum1[maxn],sum2[maxn],ans,cur; int main(){ scanf("%d%d",&n,&p); for(int i=1;i<=p;i++)scanf("%d%d",&l[i],&r[i]); for(int i=1;i<=p;i++) for(int j=l[i];j<=r[i];j++) a[j]++; for(int i=1;i<=n;i++){ sum1[i]=sum1[i-1]; sum2[i]=sum2[i-1]; if(a[i]==1)sum1[i]++; if(a[i]==2)sum2[i]++; if(a[i])cur++; } // for(int i=1;i<=n;i++)printf("%d ",sum1[i]);puts(""); // for(int i=1;i<=n;i++)printf("%d ",sum2[i]);puts(""); for(int i=1;i<=p;i++){ for(int j=i+1;j<=p;j++){ int now=cur; int l1=l[i],r1=r[i],l2=l[j],r2=r[j]; if(l1>l2){ swap(l1,l2); swap(r1,r2); } if(r1<l2){//两个区间互不覆盖 now-=sum1[r1]-sum1[l1-1]; now-=sum1[r2]-sum1[l2-1]; } else{ int l3=max(l1,l2); int r3=min(r1,r2); now-=sum1[r1]-sum1[l1-1]; now-=sum1[r2]-sum1[l2-1]; now-=sum2[r3]-sum2[l3-1]; } ans=max(ans,now); } } printf("%d\n",ans); return 0; }