zoukankan      html  css  js  c++  java
  • POJ2528Mayor's posters(离散化 + 线段树)

    题目链接:

    题意:给定一些高度都相同的海报去贴,问最后能看见几张海报

    The picture below illustrates the case of the sample input.

    { 8,9,10}那张被覆盖看不到,

    分析:看了大神们的博客大神是一看就是线段树,可是我都知道是线段树了也不知道怎么做,真是弱的一逼;

    线段树分析就是对于每一个海报所在的区间设置一个不同的数字,然后就统计有几个不同的数字即所求解,就是线段树区间更改

    技巧:离散化

    如果按照这个墙的宽度来设置线段树的话,很大,内存会超。考虑到海报的个数不会很多,所以根据海报的区间的两个端点来进行离散处理,

    拿例子来说,{1,4} {2,6} {8,10} {3,4} {7,10} ,所以需要的点为 1, 2, 3, 4, 6, 7, 8 ,10,令x[1] = 1, x[2] = 2,x[3] = 3,x[4] = 4,x[5] = 6,x[6] = 7,x[7] = 8, x[8] = 10,就将原来大的 【 1,10】区间变成了【1,8】这就是离散化

    还有一个bug,如果这组样例: {1,10} {1,3} {5,10} 就离散成了 x[1] = 1, x[2] = 3, x[3] = 5, x[4] = 10,

    第一张海报时候{1,10},对于离散化后的处理时,{1,4}

    第二张{1,3}, 对于离散化后的就是{1,2}

    第三张{5,10},对于离散化后的就是{3,4}

    对于离散化后的来统计,最后结果是2,而实际确实3,原因就是 3到5之间有4而离散化之后就把4给去掉了,这就是一个bug,处理方法就是把相邻的两个数如果差大于1就在添加一个数

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <cstdio>
      5 using namespace std;
      6 const int Max = 100000; //根据海报的个数来设置数组
      7 struct node
      8 {
      9     int l,r;
     10     int cover; //海报的编号
     11     int tag;  //懒惰标志
     12 };
     13 node tree[Max * 8];
     14 int t[4 * Max + 10],cnt,res[Max * 4 + 10];
     15 int a[Max + 10],b[Max + 10];
     16 void buildTree(int left, int right, int k)
     17 {
     18     tree[k].l = left;
     19     tree[k].r = right;
     20     tree[k].cover = 0;
     21     tree[k].tag = -1;
     22     if(left == right)
     23         return;
     24     int mid = (left + right) / 2;
     25     buildTree(left, mid, k * 2);
     26     buildTree(mid + 1, right, k * 2 + 1);
     27 }
     28 int Find(int l, int r, int key, int temp[])
     29 {
     30     while(r >= l)
     31     {
     32         int mid = (l + r) / 2;
     33         if(temp[mid] == key)
     34             return mid;
     35         else if(temp[mid] > key)
     36         {
     37             r = mid - 1;
     38         }
     39         else
     40         {
     41             l = mid + 1;
     42         }
     43     }
     44     return -1;
     45 }
     46 void upDate(int left, int right, int k, int num)
     47 {
     48     if(tree[k].l == left && tree[k].r == right)
     49     {
     50         tree[k].cover = num;
     51         tree[k].tag = num;
     52         return;
     53     }
     54     if(tree[k].tag != -1)
     55     {
     56         tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag;
     57         tree[k * 2].cover = tree[k * 2 + 1].cover = tree[k].tag;
     58         tree[k].tag = -1;
     59     }
     60     int mid = (tree[k].l + tree[k].r) / 2;
     61     if(right <= mid)
     62     {
     63         upDate(left, right, k * 2, num);
     64     }
     65     else if(mid < left)
     66     {
     67         upDate(left, right, k * 2 + 1, num);
     68     }
     69     else
     70     {
     71         upDate(left, mid, k * 2, num);
     72         upDate(mid + 1, right, k * 2 + 1, num);
     73     }
     74 }
     75 void Search(int k)
     76 {
     77     if(tree[k].tag != -1)
     78     {
     79         tree[k].cover = tree[k].tag;
     80         tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag;
     81         tree[k * 2].cover = tree[k * 2 + 1].cover = tree[k].tag;
     82         tree[k].tag = -1;
     83     }
     84 
     85     if(tree[k].l == tree[k].r)
     86     {
     87         res[ tree[k].cover ] = 1; // 看看每一个点的海报编号
     88         return;
     89     }
     90     Search(k * 2);
     91     Search(k * 2 + 1);
     92 }
     93 int main()
     94 {
     95     int test,n;
     96     scanf("%d", &test);
     97     while(test--)
     98     {
     99         scanf("%d", &n);
    100         cnt = 0;
    101         for(int i = 1; i <= n; i++)
    102         {
    103             scanf("%d%d", &a[i], &b[i]);
    104             t[ cnt++ ] = a[i];
    105             t[ cnt++ ] = b[i]; //将所有的端点都放入t中
    106         }
    107         sort(t, t + cnt);
    108         int cnt1 = 1;
    109         for(int i = 1; i < cnt; i++)
    110         {
    111             if(t[i] != t[i - 1])  //去掉相同的
    112                 t[ cnt1++ ] = t[i];
    113         } 
    114         for(int i = cnt1 - 1; i > 0; i--)
    115         {
    116             if(t[i] - t[i - 1] > 1) //如果相邻数差值大于1,就则加一个数
    117                 t[ cnt1++ ] = t[i - 1] + 1;
    118         }
    119         sort(t, t + cnt1); //加完之后排序,此时已经离散完毕
    120         for(int i = cnt1; i > 0; i--)
    121             t[i] = t[i - 1];
    122         //使区间为1到cnt1,好处理
    123         buildTree(1, cnt1, 1);
    124 
    125         for(int i = 1; i <= n; i++)
    126         {
    127             int left = Find(1, cnt1, a[i], t);  //二分查找出每个区间的端点在离散化后的数组中的位置
    128             int right = Find(1, cnt1, b[i], t);
    129             upDate(left, right, 1, i);  //更新,设置覆盖位为 i
    130         }
    131         memset(res, 0, sizeof(res));
    132         Search(1); //从根开始查找
    133         int ans = 0;
    134         for(int i = 1; i <= n; i++)
    135             if(res[i])
    136             ans++;
    137         printf("%d
    ", ans);
    138     }
    139     return 0;
    140 }
    View Code
  • 相关阅读:
    php 工厂模式实例
    nginx多虚拟主机配置
    PHP提高编程效率的方法
    PHP 多态
    锁机制之PHP文件锁
    深入认识javascript中的eval函数(转载)
    PHP&MYSQL 常用的一些性能检测
    寒假作业1:问答题
    软件测试基础知识总结
    七种测试驱动模式
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5236380.html
Copyright © 2011-2022 走看看