题目链接:http://codeforces.com/contest/1029/problem/C
题目大意:给出n条线段,第 i 条线段的左端点为 li ,右端点为 ri。现在你可以将这n条线段中的一条删去,问你要删去哪条线段才能使被剩下的n-1条线段所覆盖的区域尽可能的长。
题目思路:线段覆盖的话,我们可以考虑用线段树来维护,由于本题的 li 和 ri 都可以达到1e9,所以我们要先离散化一下,再用线段树维护。线段树中维护的是一段区间内被线段覆盖的最大次数。接着就可以枚举删掉哪条线段,每次先将这条线段从线段树中删去,再找到线段树内值为n-1的区间,由于线段树内维护的是最大值,所以我们可以用一个查询函数queryl来查询被n-1条线段覆盖的区间的左端点,用queryr来查询被n-1条线段覆盖的区间的右端点。查询的时候只需要根据情况选择往左子树查询,或者往右子树查询即可。复杂度为O(n*logn)。
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>pll;
typedef pair<int, int>pii;
typedef vector<int> VI;
const int inf = 0x3f3f3f3f;
const int MX = 1e6 + 7;
int n;
struct node {
int l, r;
} a[MX];
VI h;
int get_id(int x) {
return lower_bound(h.begin(), h.end(), x) - h.begin() + 1;
}
int MAX[MX << 2], tag[MX << 2];
void push_up(int rt) {
MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]);
}
void push_down(int rt) {
if (tag[rt] != 0) {
MAX[rt << 1] += tag[rt];
MAX[rt << 1 | 1] += tag[rt];
tag[rt << 1] += tag[rt];
tag[rt << 1 | 1] += tag[rt];
tag[rt] = 0;
}
}
void update(int L, int R, int d, int l, int r, int rt) {
if (L <= l && r <= R) {
tag[rt] += d;
MAX[rt] += d;
return;
}
push_down(rt);
int m = (l + r) >> 1;
if (L <= m) update(L, R, d, lson);
if (R > m) update(L, R, d, rson);
push_up(rt);
}
int queryl(int d, int l, int r, int rt) {
if (l == r) return l;
push_down(rt);
int m = (l + r) >> 1;
if (MAX[rt << 1] >= d) return queryl(d, lson);
else return queryl(d, rson);
}
int queryr(int d, int l, int r, int rt) {
if (l == r) return l;
push_down(rt);
int m = (l + r) >> 1;
if (MAX[rt << 1 | 1] >= d) return queryr(d, rson);
else return queryr(d, lson);
}
int main() {
//FIN;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].l, &a[i].r);
h.pb(a[i].l); h.pb(a[i].r);
}
sort(h.begin(), h.end());
h.erase(unique(h.begin(), h.end()), h.end());
int N = n << 1;
for (int i = 1; i <= n; i++) {
int l = get_id(a[i].l), r = get_id(a[i].r);
update(l, r, 1, 1, N, 1);
}
int ans = 0;
for (int i = 1; i <= n; i++) {
int l = get_id(a[i].l), r = get_id(a[i].r);
update(l, r, -1, 1, N, 1);
if (MAX[1] >= n - 1) {
int L = queryl(n - 1, 1, N, 1), R = queryr(n - 1, 1, N, 1);
L = h[L - 1], R = h[R - 1];
ans = max(ans, R - L);
}
update(l, r, 1, 1, N, 1);
}
printf("%d\n", ans);
return 0;
}