CodeForces-1132C Painting the Fence
題目鏈接
https://vjudge.net/problem/CodeForces-1132C
題面
Description
You have a long fence which consists of \(n\) sections. Unfortunately, it is not painted, so you decided to hire \(q\) painters to paint it. \(i\)-th painter will paint all sections \(x\) such that \(l_i \le x \le r_i\).
Unfortunately, you are on a tight budget, so you may hire only \(q - 2\)
You want to maximize the number of painted sections if you choose \(q - 2\) painters optimally. A section is considered painted if at least one painter paints it.
Input
The first line contains two integers \(n\) and \(q\) (\(3 \le n, q \le 5000\)
Then \(q\) lines follow, each describing one of the painters: \(i\)-th line contains two integers \(l_i\) and \(r_i\) (\(1 \le l_i \le r_i \le n\)).
Output
Print one integer — maximum number of painted sections if you hire \(q - 2\)
Examples
Input
7 5
1 4
4 5
5 6
6 7
3 5
Output
7
Input
4 3
1 1
2 2
3 4
Output
2
Input
4 4
1 1
2 2
2 3
3 4
Output
3
題意
墻長為n,q個工人,每個工人固定粉刷一個區間,區間可能重疊,現在要去掉兩個工人,求剩下q-2個工人最多粉刷多少墻
題解
我們可以\(n^2\)枚舉去掉的兩個工人,然後O(1)查詢剩下了多少墻
O(1)查詢的方法是:先預處理出每一段墻有多少工人刷,然後處理出每一個工人刷的只有他自己刷的墻的長度,然後預處理出只有兩個工人刷的墻的區間的前綴和,然後對於枚舉的兩個工人,刷過的墻的總數首先要減去兩個工人刷的墻的部分中只有一個人刷的部分,因為去掉這個工人這個墻就沒人刷了,如果兩個工人的覆蓋區間有重疊,假設重疊區間\([L,R]\),要減去的區間就是\([L,R]\)中只有兩個工人刷的部分,因為去掉這兩個工人這段墻就沒人刷了
結果取最大值即可
AC代碼
#include <bits/stdc++.h>
#define N 5050
using namespace std;
struct seg {
int l, r;
} a[N];
int pre[N];
int pre1[N];
int pre2[N];
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int n, q;
scanf("%d%d", &n, &q);
int sum = 0;
for (int i = 1; i <= q; i++) {
scanf("%d%d", &a[i].l, &a[i].r);
pre[a[i].l]++; pre[a[i].r + 1]--;
}
for (int i = 1; i <= n; i++) {
pre[i] += pre[i - 1];
}
for (int i = 1; i <= n; i++) {
if (pre[i]) sum++;
}
for (int i = 1; i <= n; i++) {
if (pre[i] == 2) pre1[i]++;
}
for (int i = 1; i <= n; i++) {
pre1[i] += pre1[i - 1];
}
for (int i = 1; i <= q; i++) {
for (int j = a[i].l; j <= a[i].r; j++) {
if (pre[j] == 1) pre2[i]++;
}
}
int L, R;
int ans = 0;
for (int i = 1; i <= q; i++) {
for (int j = i + 1; j <= q; j++) {
L = max(a[i].l, a[j].l);
R = min(a[i].r, a[j].r);
int tmp = sum;
if (R >= L) {
tmp = tmp - (pre1[R] - pre1[L - 1]);
}
tmp -= pre2[i] + pre2[j];
ans = max(tmp, ans);
}
}
printf("%d\n", ans);
return 0;
}
CodeForces-1132C Painting the Fence