codeforces 1132C - Painting the Fence -線段的最大區間覆蓋

題目鏈接: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章