题目连接:https://codeforces.com/contest/1132/problem/Cc++
题意:数组
栅栏有 $n$ 个节,有 $q$ 我的能够雇佣来涂栅栏,第 $i$ 我的能够涂第 $l_i$ 节到第 $r_i$ 节。优化
可是如今预算紧张,因此只能雇佣 $q-2$ 我的,你想确认雇佣哪 $q-2$ 我的使得涂色栅栏的节数最大。spa
题解:code
首先看到 $n$ 的范围,就能够想到大概能够枚举第一个不雇佣的人再枚举第二个不雇佣的人,时间复杂度在 $O(n^2)$ 左右。blog
先假定第一个不雇佣的人是第 $x$ 我的,而后剩下的 $q-1$ 我的,他们的涂栅栏状况用数组 $c$ 记录,$c_i$ 表示第 $i$ 节有多少人涂。ci
而后咱们用另外一个数组 $d$ 对应到数组 $c$,若 $c_i = 1$,则 $d_i = 1$;不然 $d_i = 0$。这样一来就能对每一个人,用前缀和优化 $O(1)$ 地求出仅他能涂的栅栏节数。get
这样,咱们用数组 $c$ 全部 $c_i > 0$ 的 $i$ 的数目减去仅这我的能涂抹的节数,就知道最终能涂多少节。it
AC代码:class
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; #define mk(x,y) make_pair(x,y) #define fi first #define se second const int maxn=5e3+10; int n,q; P p[maxn]; int cnt[maxn],sum[maxn]; int main() { cin>>n>>q; memset(cnt,0,sizeof(cnt)); for(int i=1;i<=q;i++) { cin>>p[i].fi>>p[i].se; for(int k=p[i].fi;k<=p[i].se;k++) cnt[k]++; } int ans=0; for(int x=1;x<=q;x++) { for(int k=p[x].fi;k<=p[x].se;k++) cnt[k]--; int tot=0; for(int k=1;k<=n;k++) { tot+=(cnt[k]>0); if(cnt[k]==1) sum[k]=1; else sum[k]=0; sum[k]+=sum[k-1]; } int Max=0; for(int y=1;y<=q;y++) { if(x==y) continue; Max=max(Max,tot-(sum[p[y].se]-sum[p[y].fi-1])); } ans=max(ans,Max); for(int k=p[x].fi;k<=p[x].se;k++) cnt[k]++; } cout<<ans<<endl; }