题目链接: http://poj.org/problem?id=2528
题意: 第一行输入一个 t 表 t 组输入, 对于每组输入: 第一行 n 表接下来有 n 行形如 l, r 的输入, 表在区间 [l, r] 贴一张海报, 问最终能看见几张不同的海报;
思路: 线段树区间替换, 每次 update 时都会给对应区间加一个 lazy 标记, 最终统计标记的种数即为答案;
注意: 题目给出的 l, r 很大, 需要离散化, 和普通的离散化不同, 因为本题中每个单位是代表长度为一的一个区间,而非一个点, 所以对于两个数 a, b, 若 b > a + 1,
hash[a] = cnt, 那么hash[b] = cnt + 2 而非 hahs[b] = cnt + 1;不然对于一些数据会出错.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <string.h> 5 #include <map> 6 #define lson l, mid, rt << 1 7 #define rson mid + 1, r, rt << 1 | 1 8 using namespace std; 9 10 const int MAXN = 1e4 + 10; 11 int l[MAXN], r[MAXN], gel[MAXN << 1], lazy[MAXN << 4]; 12 bool vis[MAXN << 1]; 13 map<int, int> hash; 14 int ans; 15 16 void push_down(int rt){//将当前标记向下一层更新 17 if(lazy[rt] != -1){ 18 lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt]; 19 lazy[rt] = -1; 20 } 21 } 22 23 void update(int L, int R, int x, int l, int r, int rt){//区间替换 24 if(L <= l && R >= r){ 25 lazy[rt] = x; 26 return; 27 } 28 push_down(rt); 29 int mid = (l + r) >> 1; 30 if(L <= mid) update(L, R, x, lson); 31 if(R > mid) update(L, R, x, rson); 32 } 33 34 void query(int l, int r, int rt){ 35 if(lazy[rt] != -1){//标记的种数即为答案 36 if(!vis[lazy[rt]]){ 37 ans++; 38 vis[lazy[rt]] = true; 39 } 40 return; 41 } 42 if(l == r) return; 43 int mid = (l + r) >> 1; 44 query(lson); 45 query(rson); 46 } 47 48 int main(void){ 49 int t, n; 50 scanf("%d", &t); 51 while(t--){ 52 int indx = 0, cnt = 1; 53 scanf("%d", &n); 54 for(int i = 0; i < n; i++){ 55 scanf("%d%d", &l[i], &r[i]); 56 gel[indx++] = l[i]; 57 gel[indx++] = r[i]; 58 } 59 sort(gel, gel + indx); 60 hash[gel[0]] = cnt; 61 for(int i = 1; i < indx; i++){ //hash 62 if(gel[i] > gel[i - 1] + 1){ 63 cnt += 2; 64 hash[gel[i]] = cnt; 65 }else if(gel[i] > gel[i - 1]){ 66 cnt += 1; 67 hash[gel[i]] = cnt; 68 } 69 } 70 memset(lazy, -1, sizeof(lazy)); 71 memset(vis, false, sizeof(vis)); 72 for(int i = 0; i < n; i++){ 73 update(hash[l[i]], hash[r[i]], i, 1, cnt, 1); 74 } 75 ans = 0; 76 query(1, cnt, 1); 77 printf("%d\n", ans); 78 } 79 return 0; 80 }