題目鏈接:http://codeforces.com/problemset/problem/1132/C
題目大意:就是有個n長的柵欄,然後每個油漆工可以染的區域不同
給你q讓你選出q-2個人使得被染色的柵欄最多
思路:Q的範圍允許O(n*n)複雜度,先預處理每個格子被覆蓋非0次,被覆蓋1次,被覆蓋2次的情況,再暴力枚舉去掉哪兩條就ok,假如去掉X和Y兩條,那麼覆蓋數量減少爲X和Y交集部分的覆蓋2次的格子數加上X和Y部分並集的覆蓋1次的格子數,這些通過前綴和方便求出來。
對於並集的求法,並不需要求並集。因爲他們的交集覆蓋了至少爲2次。所以把這兩個直接減去就可以了。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int sum[5005], f[5005], one[5005], tow[5005];
int L[5005], R[5005];
int fun(int i, int j){
if(L[i]>L[j]){
swap(i, j);
}
if(L[j]>R[i]){
return 0;
}
int t=min(R[i], R[j]);
return max(0, tow[t]-tow[L[j]-1]);
}
int main()
{
int n, q;
scanf("%d%d", &n, &q);
for(int i=1; i<=q; i++){
scanf("%d%d", &L[i], &R[i]);
sum[L[i]]++, sum[R[i]+1]--;
}
for(int i=1; i<=n; i++){
sum[i]+=sum[i-1];
f[i]=f[i-1];
one[i]=one[i-1];
tow[i]=tow[i-1];
if(sum[i]){
f[i]+=1;
}
if(sum[i]==1){
one[i]++;
}
if(sum[i]==2){
tow[i]++;
}
}
LL ans=0;
for(int i=1; i<=q; i++){
for(int j=i+1; j<=q; j++){
LL s=f[n];
s-=fun(i, j);//交集
s-=(one[R[i]]-one[L[i]-1]);
s-=(one[R[j]]-one[L[j]-1]);
ans=max(s, ans);
}
}
printf("%lld\n", ans);
return 0;
}