poj2528(线段树区间替换&离散化)

题目链接: 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 }
View Code

 

转载于:https://www.cnblogs.com/geloutingyu/p/7010133.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值