题目链接:http://poj.org/problem?id=2528
如果不考虑区间大小的话,是线段树的成段更新,但是由于区间的范围实在太大,达到1e7,但是其实只会每次最多只输入1e5个区间。所以需要对区间进行离散化。
离散化
例如输入4个区间为[1, 4] [3, 7] [4, 8] [5, 10]
将左右区间端点按大小排序并去重得
1,3,4,5,7,8,10
对其重新编号
1 —> 1
3 —> 2
4 —> 3
5 —> 4
7 —> 5
8 —> 6
10 —> 7
所以得到对应的区间为[1, 3] [2, 5] [3, 6] [4, 7],每次转换区间的时候可以利用二分查找。
此题的离散化需注意,若按照以上的方法离散化的话,某些特殊数据会出现问题。
比如3个区间。
[1, 5] [1, 2] [4, 5]
若按照以上方法离散化的话,输出的答案为2,但是实际答案应该是3。问题出在将4转换为3后,2与4之间原本有的距离被忽视了。所以可以考虑在2与4之间添加一个数,防止离散化后此段距离为空。
代码如下。
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#include <cstring>
#include <cassert>
using namespace std;
const int maxn = 100005;
const int INF = 0x7fffffff;
const int mod = 1e7+7;
#define LSON l, m, rt << 1
#define RSON m + 1, r, rt << 1 | 1
#define ESP 1e-7
struct Poster {
int l, r;
};
Poster p[maxn];
int poster[maxn << 2];
int lazy[maxn << 2];
int hav;
bool vis[maxn];
int x[maxn];
int cot;
void PushDown(int rt) {
if (lazy[rt]) {
lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
poster[rt << 1] = lazy[rt];
poster[rt << 1 | 1] = lazy[rt];
lazy[rt] = 0;
}
}
void Build(int l, int r, int rt) {
if (l == r) return ;
lazy[rt] = 0;
poster[rt] = 0;
int m = (l + r) >> 1;
Build(LSON);
Build(RSON);
}
void Update(int L, int R, int num, int l, int r, int rt) {
if (L <= l && r <= R) {
poster[rt] = num;
lazy[rt] = num;
return ;
}
PushDown(rt);
int m = (l + r) >> 1;
if (L <= m) Update(L, R, num, LSON);
if (R > m) Update(L, R, num, RSON);
}
void Query(int l, int r, int rt) {
if (l == r) {
if (!vis[poster[rt]] && poster[rt]) {
hav++;
vis[poster[rt]] = true;
}
return ;
}
PushDown(rt);
int m = (l + r) >> 1;
Query(LSON);
Query(RSON);
}
int BinarySearch(int finded) {
int l = 1, r = cot;
if (x[r] == finded) return r;
if (x[l] == finded) return l;
while (r - l > 1) {
int m = (l + r) >> 1;
if (x[m] == finded)
return m;
else if (x[m] < finded)
l = m;
else r = m;
}
return -1;
}
int main() {
int t;
scanf("%d", &t);
for (int n_case = 1; n_case <= t; n_case++) {
int n, nn = 0;
scanf("%d", &n);
int r_max = -1;
cot = 1, hav = 0;
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; i++) {
int l, r;
scanf("%d%d", &l, &r);
p[i].l = l;
p[i].r = r;
r_max = max(r, r_max);
x[++nn] = l;
x[++nn] = r;
}
//离散化
sort(x + 1, x + 1 + nn);
for (int i = 2; i <= nn; i++)//去重复
if (x[i] != x[cot]) x[++cot] = x[i];
int tmp = cot;
for (int i = 2; i <= tmp; i++)//添加某些数
if (x[i] - x[i - 1] > 1) x[++cot] = (x[i] + x[i - 1]) >> 1;
sort(x + 1, x + 1 + cot);
Build(1, cot, 1);
for (int i = 1; i <= n; i++) {
int l = BinarySearch(p[i].l);
int r = BinarySearch(p[i].r);
Update(l, r, i, 1, cot, 1);
}
Query(1, cot, 1);
printf("%d\n", hav);
}
return 0;
}