题目链接在这里
题目大意:
在墙上贴海报,每张海报占据[l, r]区间,海报之间可能存在覆盖。问所有的海报贴完之后,能有几张海报可以被看到。
解题思路:
如果暴力扫一遍的话肯定会超时,所以应该用线段树。但是区间太大了,所以要考虑离散化。
普通的离散化有问题,这里参考了一位博主的博客进行离散化。
我一直RE,数组开打了4倍才AC的,如果有RE的同志记得开大数组试试。
代码如下:
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
#define clr(x) memset(x, 0, sizeof(x));
#define rep(i, n) for(int i = 0; i < n; ++i)
#define rl (rt << 1)
#define rr (rt << 1 | 1)
using namespace std;
const int MaxN = 40010;
struct Point{
int l, r;
}point[MaxN];
struct Node{
int l, r, mid;
int w, mark;
}tree[MaxN << 2];
int n, ans;
int pos[MaxN << 1];
bool vis[MaxN << 1];
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mid = (l + r) >> 1;
tree[rt].mark = -1;
if(l == r) return;
build(l, tree[rt].mid, rl);
build(tree[rt].mid + 1, r, rr);
}
void update(int l, int r, int rt, int w){
if(tree[rt].l == l && tree[rt].r == r){
tree[rt].w = w;
tree[rt].mark = 1;
return;
}
if(tree[rt].mark == 1){
tree[rl].w = tree[rt].w;
tree[rl].mark = 1;
tree[rr].w = tree[rt].w;
tree[rr].mark = 1;
tree[rt].mark = -1;
}
if(tree[rt].mid >= r)
update(l, r, rl, w);
else if(tree[rt].mid < l)
update(l, r, rr, w);
else{
update(l, tree[rt].mid, rl, w);
update(tree[rt].mid + 1, r, rr, w);
}
}
void query(int l, int r, int rt){
if(tree[rt].mark == 1){
if(!vis[tree[rt].w]){
++ans;
vis[tree[rt].w] = true;
}
return;
}
if(l == r) return;
query(l, tree[rt].mid, rl);
query(tree[rt].mid + 1, r, rr);
}
int main(){
int t;
scanf("%d", &t);
while(t--){
int cnt = 0;
memset(vis, false, sizeof(vis));
ans = 0;
scanf("%d", &n);
rep(i, n){
scanf("%d %d", &point[i].l, &point[i].r);
pos[cnt++] = point[i].l;
pos[cnt++] = point[i].r;
}
sort(pos, pos + cnt);
cnt = unique(pos, pos + cnt) - pos;
for(int i = cnt - 1; i; --i){
if(pos[i] != pos[i - 1] + 1) pos[cnt++] = pos[i - 1] + 1;
}
sort(pos, pos + cnt);
build(0, cnt, 1);
rep(i, n){
int l = lower_bound(pos, pos + cnt, point[i].l) - pos;
int r = lower_bound(pos, pos + cnt, point[i].r) - pos;
update(l, r, 1, i);
}
query(0, cnt, 1);
printf("%d\n", ans);
}
return 0;
}