F. The Treasure of The Segments
链接
题意
有n条线段(1<= n <= 2e5),线段两端L,R(1<= L <= R <= 1e9)
问删掉最小数量的线段,使所有的线段不重合?
题解一
对于线段i来说,需要删掉T[j] 大于 a[i].s 的 以及 S[j]大于a[i].t。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
typedef long long ll;
const int MAX = 2e5 + 5;struct line{
ll s, t;
};line a[MAX];
ll S[MAX], T[MAX];int main() {
int tt;scanf("%d", &tt);while(tt--) {
int n;scanf("%d", &n);for (int i = 0; i < n; i++) {
scanf("%lld%lld", &a[i].s, &a[i].t);S[i] = a[i].s;T[i] = a[i].t;}sort(S, S + n);sort(T, T + n);int maxx = MAX;for(int i = 0; i < n; i++) {
int ans = 0;ans += (lower_bound(T, T + n, a[i].s) - T);ans += (n - (upper_bound(S, S + n, a[i].t) - S));maxx = min(maxx, ans);}printf("%d\n", maxx);}
}
题解二
问题转化为 n - 重合数量最多
按照L排序,从小到大,对于第i个线段,把所有L小于t的压入优先队列(优先队列按照R排序),此时bit函数第i为覆盖的是优先队列的大小,前i位因为新加入i根线段,所有值++。如果最小R值(优先队列top)小于t,弹出,取这个弹出线段的覆盖线段max值。
由于 LR 太大 ==》 离散化
区间加减 ==》树状数组
注意:
树状数组最好从1开始(个人认为) 这样的话,离散化后值为 位置 + 1
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int MAX = 2e5 + 12;struct line {
ll s, t, n;bool operator<(const line &a)const {
return a.t < t;}
};int bit[MAX + 10];int sum(int i) {
int ans = 0;while(i) {
ans += bit[i];i -= i & -i;}return ans;
}
void add(int k, int x) {
while(k < MAX) {
bit[k] += x;k += k & -k;}
}bool cmp(line a, line b) {
if(a.s != b.s) return a.s < b.s;return a.t < b.t;
}void LRadd(int L, int R, int x) {
add(L, x);add(R + 1, -x);
}vector<ll> v;
line a[MAX];
int main() {
int T;scanf("%d", &T);while(T--) {
v.clear();int n;scanf("%d", &n);for(int i = 1; i <= n; i++) bit[i] = 0;for(int i = 1; i <= n; i++) {
scanf("%lld %lld", &a[i].s, &a[i].t);v.push_back(a[i].s);v.push_back(a[i].t);}sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());for(int i = 1; i <= n; i++) {
a[i].s = lower_bound(v.begin(), v.end(), a[i].s) - v.begin() + 1;a[i].t = lower_bound(v.begin(), v.end(), a[i].t) - v.begin() + 1;}sort(a + 1, a + 1 + n, cmp);for(int i = 1; i <= n; i++) a[i].n = i;priority_queue<line>que;int pos = 1;//对于t来说int maxx = -1;for(int t = 1; t < 2 * n + 10; t++) {
while(pos <= n && a[pos].s <= t) {
que.push(a[pos]);LRadd(1, pos - 1, 1);LRadd(pos, pos, que.size());pos++;}while(1) {
if(que.top().t > t || que.empty()) break;maxx = max(maxx, sum(que.top().n));que.pop();}}printf("%d\n", n - maxx);}
}