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 }

 

posted @ 2016-04-04 21:53  Recoder  阅读(154)  评论(0编辑  收藏  举报