POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528
给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板。
很明显的线段树区间更新问题,每次放置木板就更新区间里的值。由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案。
写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 const int MAXN = 2e4 + 5; 8 struct data { 9 int l , r , sum; 10 }T[MAXN << 2]; 11 map <int , int> mp; 12 int x[MAXN] , y[MAXN] , cont , id[MAXN]; 13 14 void init(int p , int l , int r) { 15 int mid = (l + r) >> 1; 16 T[p].l = l , T[p].r = r; 17 if(l == r) { 18 T[p].sum = 0; 19 return ; 20 } 21 init(p << 1 , l , mid); 22 init((p << 1)|1 , mid + 1 , r); 23 T[p].sum = T[p << 1].sum + T[(p << 1)|1].sum; 24 } 25 26 int query(int index , int p) { 27 int mid = (T[p].l + T[p].r) >> 1; 28 if(index == T[p].l && T[p].r == index) { 29 return T[p].sum; 30 } 31 if(T[p].sum) { 32 T[p << 1].sum = T[(p << 1)|1].sum = T[p].sum; 33 T[p].sum = 0; 34 } 35 if(index <= mid) { 36 query(index , p << 1); 37 } 38 else { 39 query(index , (p << 1)|1); 40 } 41 } 42 43 void updata(int p , int l , int r , int val) { 44 int mid = (T[p].l + T[p].r) >> 1; 45 if(T[p].l >= l && T[p].r <= r) { //找到了区间,更新这个区间 46 T[p].sum = val; 47 return ; 48 } 49 if(T[p].sum) { //重点注意,如果这个区间被访问了,并且这个区间要更新,就要将这个区间的值更新到其左右孩子的节点,并且要将这个区间的值清空,这样才能算是覆盖 50 T[p << 1].sum = T[(p << 1)|1].sum = T[p].sum; 51 T[p].sum = 0; 52 } 53 if(r <= mid) { 54 updata(p << 1 , l , r , val); 55 } 56 else if(l > mid) { 57 updata((p << 1)|1 , l , r , val); 58 } 59 else { 60 updata(p << 1 , l , mid , val); 61 updata((p << 1)|1 , mid + 1 , r , val); 62 } 63 } 64 65 int main() 66 { 67 int t , n; 68 scanf("%d" , &t); 69 while(t--) { 70 scanf("%d" , &n); 71 mp.clear(); 72 cont = 0; 73 for(int i = 1 ; i <= n ; i++) { 74 scanf("%d %d" , x + i , y + i); 75 if(!mp[x[i]]) { 76 id[++cont] = x[i]; 77 mp[x[i]]++; 78 } 79 if(!mp[y[i]]) { 80 id[++cont] = y[i]; 81 mp[y[i]]++; 82 } 83 } 84 sort(id + 1 , id + cont + 1); 85 int len = -1; //离散化之后的最大的数 86 for(int i = 1 ; i <= n ; i++) { //离散化 87 x[i] = lower_bound(id + 1 , id + cont + 1 , x[i]) - id; 88 len = max(x[i] , len); 89 y[i] = lower_bound(id + 1 , id + cont + 1 , y[i]) - id; 90 len = max(y[i] , len); 91 } 92 init(1 , 1 , len); 93 for(int i = 1 ; i <= n ; i++) { 94 updata(1 , x[i] , y[i] , i); 95 } 96 mp.clear(); 97 int res = 0; 98 for(int i = 1 ; i <= len ; i++) { 99 int temp = query(i , 1); 100 if(!mp[temp] && temp) { 101 res++; 102 mp[temp]++; 103 } 104 } 105 printf("%d\n" , res); 106 } 107 }