主要是参考了这个博客 地址戳这儿
题目大意:n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000) 。求出最后还能看见多少张海报。
对于输入要离散化,之后线段树维护张贴的状态。
留意由于一般的离散化可能导致一些区间被“挤压掉”
比如
1-10 1-4 5-10
1-10 1-4 6-10 被处理成了一样的情况导致错漏。
方法是在相差超过1的相邻点插多一个点,使得离散化的时候不会挤压在一起。还有要注意的地方就是空间开多大,一般是要开4倍点空间,但是由于上述增加点的操作会新增加一些点,直接4*2e4是不行的,直接开8×2e4就ok了。
还有,离散化映射的时候能不用STL最好,宁可开个1kw的数组映射,或者用二分法映射,否则容易TLE。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std; #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
const int maxN=1e4+;
int N, M, K, T; struct Post{int x, y;}nd[maxN];
int g[maxN * ], sg[maxN * ], vis[maxN];
int ans; #define lson l,m,rt*2
#define rson m+1,r,rt*2+1 void push_down(int rt) {
if (sg[rt] == -) return;
sg[rt * ] = sg[rt * + ] = sg[rt];
sg[rt] = -;
}
void update(int L, int R, int C, int l, int r, int rt) {
if (L <= l && r <= R) {
sg[rt] = C;
return;
}
push_down(rt);
int m = (l + r) / ;
if (L <= m) update(L, R, C, lson);
if (R > m) update(L, R, C, rson);
}
void query(int l, int r, int rt) {
if (sg[rt] != -) {
if (vis[sg[rt]] == )
++ans;
vis[sg[rt]] = ;
return;
}
if (l == r) return;
int m = (l + r) / ;
query(lson);
query(rson);
} int main () {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
scanf("%d", &T);
while (T--) {
// 输入及离散化
scanf("%d", &N);
int cnt = ;
FOR(i, , N) {
scanf("%d%d", &nd[i].x, &nd[i].y);
g[cnt++] = nd[i].x;
g[cnt++] = nd[i].y;
}
sort(g, g + cnt);
int m = unique(g, g + cnt) - g;
int ocnt = m;
FOR(i, , ocnt - )
if (g[i + ] - g[i] > )
g[m++] = g[i] + ;
sort(g, g + m); // 建线段树以及输出答案
memset(sg, -, sizeof sg);
memset(vis, , sizeof vis); FOR(i, , N) {
int l = lower_bound(g, g + m, nd[i].x) - g;
int r = lower_bound(g, g + m, nd[i].y) - g;
update(l, r, i, , m, );
}
ans = ;
query(, m, );
printf("%d\n", ans);
}
return ;
}