题目
- 题目链接:http://poj.org/problem?id=2528
- 题意:第一行T:测试用例数量;第二行n,海报的数目;接下来n行,l, r,:【l, r】区间被一张海报覆盖;问最终能看到多少的海报
思路
- 典型的线段树,区间覆盖。不过这里(l, r)的最大值是1千万, built(1, 一千万, 1), 肯定会超时,要将坐标离散化;
- 离散化: 比如原题测试样例n张海报区间时:
(1, 4), (2, 6), (8, 10), (3, 4), (7, 11);
- 离散化处理完成后就是常规的区间覆盖了
代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200005;
bool vis[maxn];
int LL[maxn], RR[maxn];
int x[maxn << 2];
int cnt;
struct{
int l, r;
int num;
}tree[maxn << 2];
int lower_bound(int l, int r, int key){
int mid = (l + r) / 2;
if(x[mid] == key) return mid;
else if(key < x[mid]) return lower_bound(l, mid - 1, key);
else return lower_bound(mid + 1, r, key);
}
void built(int s, int e, int node){
tree[node].l = s;
tree[node].r = e;
tree[node].num = 1;
int mid = (s + e) >> 1;
if(s == e){
return ;
}
built(s, mid, node << 1);
built(mid + 1, e, node << 1 | 1);
}
void update(int L, int R, int node, int num){
if(tree[node].l >= L && tree[node].r <= R){
tree[node].num = num;
return ;
}else{
if(tree[node].num != -1){
tree[node << 1].num = tree[node].num;
tree[node << 1 | 1].num = tree[node].num;
tree[node].num = -1;
}
int mid = (tree[node].l + tree[node].r) >> 1;
if(mid < L) update(L, R, node << 1 | 1, num);
else if(mid >= R) update(L, R, node << 1, num);
else{
update(mid | 1, R, node << 1 | 1, num);
update(L, mid, node << 1, num);
}
}
}
void query(int L, int R, int node){
if(tree[node].num != -1){
vis[tree[node].num] = true;
return;
}else{
int mid = (tree[node].l + tree[node].r) >> 1;
if(L > mid){
query(L, R, node << 1 | 1);
}else if(R <= mid){
query(L, R, node << 1);
}else{
query(L, mid, node << 1);
query(mid + 1, R, node << 1 | 1);
}
}
}
int main(){
int t;
cin >> t;
while(t --){
memset(vis, false, sizeof(vis));
int ans = 0, n, cnt = 0;
cin >> n;
for(int i = 0; i < n; i++){
scanf("%d %d", &LL[i], &RR[i]);
x[++cnt] = LL[i];
x[++cnt] = RR[i];
}
sort(x + 1, x + cnt + 1);
int count = 1;
for(int i = 2; i <= cnt; i++){
if(x[i - 1] == x[i]){
while(x[i - 1] == x[i]){
i++;
}
i--;
}else{
x[++count] = x[i];
}
}
cnt = count;
for(int i = 2; i <= count; i++){
if(x[i] - x[i - 1] > 1) x[++ cnt] = x[i - 1] + 1;
}
count = cnt;
sort(x + 1, x + count + 1);
built(1, count, 1);
for(int i = 0; i < n; i++){
int l = lower_bound(1, count, LL[i]);
int r = lower_bound(1, count, RR[i]);
update(l, r, 1, i + 1);
}
query(1, count, 1);
for(int i = 1; i <= n; i++){
if(vis[i]) ans ++;
}
cout << ans << endl;
}
return 0;
}