題目連接: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; }