• POJ 2528 线段树 成段更新+【离散化】 贴海报.cpp


    题意:

      给出了n份海报的贴在board上的起始位置和结束位置

      问最后可以看到多少份海报

     

    输入:

      n表示有n份海报

      接下来n行 每行 a b 表示海报占据了a~b的位置..

     

    思路:

      线段树成段更新

      用树的结点value表示控制范围内的海报编号..

      因为不用更新到底+查询到每一个叶子节点..所以提高了查询和更新效率..

     

      其中因为海报长度给的很大..

      所以可以使用离散化来减少空间的消耗以及查询和更新时的递归次数..

     

    Tips:

      因为给出的a b 表示的是在a~b内贴了海报..

      所以a b给的是值..但是表示的是一段范围..

      如果用正常的离散化..就可能出现

      最底下一层贴了一张海报AA..

      然后上面贴了两张相邻的海报BB 和 CC

      BB.r < CC.l

      但是离散化后因为BB和CC是相邻的..所以BB.r = CC.l

      这样~本来两张海报之间是有空隙的..可以透过空隙看到AA

      结果离散化之后就覆盖了那个空隙..

     

      解决方法就是当发现相隔的两个海报之间的距离>1就在中间加一个数..

     

    离散化的处理方式很有趣吖~~^^

    View Code
     1 for(i = 0; i < n; ++i) {
     2             scanf("%d %d", &l, &r);
     3             if(vis[l] == 0){//如果没有访问过这个点..
     4                 vis[l] = 1;
     5                 s[tot++] = l;//就把这个点加到离散化的数组里..
     6             }
     7             if(vis[r] == 0) {
     8                 s[tot++] = r;
     9                 vis[r] = 1;
    10             }
    11             node[i].l = l, node[i].r = r;
    12         }
    13 
    14         sort(s, s+tot);
    15 
    16         for(i = tot-1; i > 0; --i) {//在相邻的海报间增加一个点
    17             if(s[i] - s[i-1] > 1)
    18                 s[tot++] = s[i-1]+1;
    19         }
    20         sort(s, s+tot);
    21 
    22         for(i = 0; i < n; ++i) {//s数组的下标就是离散化后的值..
    23             l = solve(node[i].l, tot, s);
    24             r = solve(node[i].r, tot, s);
    25             modify(l, r, i, 0, tot, 1);
    26         }
    27 
    28 
    29 int solve(int key, int tot, int *arr)
    30 {
    31     int mid;
    32     int l = 0, r = tot-1;
    33     while(l <= r) {
    34         mid = (l+r)>>1;
    35         if(arr[mid] == key) return mid;
    36         if(arr[mid] > key) r = mid-1;
    37         else l = mid+1;
    38     }
    39 }

    还有问题就是if(vis[r] == 0) 有时候 r 会很大..这样写就错了~

    所以可以不管有没有增加过这个点都先放入 s 数组里~

    然后再去重..

    Code:

    View Code
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int MAXN = 40010;
      7 int lazy[MAXN<<2];
      8 int arr[MAXN];
      9 int vis[10000010];
     10 int s[MAXN];
     11 int cnt;
     12 
     13 struct Node
     14 {
     15     int r;
     16     int l;
     17 }node[MAXN];
     18 
     19 void pushDown(int rt)
     20 {
     21     if(lazy[rt] != -1) {
     22         lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
     23         lazy[rt] = -1;
     24     }
     25 }
     26 
     27 void modify(int l, int r, int x, int L, int R, int rt)
     28 {
     29     if(l <= L && r >= R) {
     30         lazy[rt] = x;
     31         return;
     32     }
     33     pushDown(rt);
     34     int mid = (L+R) >> 1;
     35     if(l <= mid) modify(l, r, x, L, mid, rt<<1);
     36     if(mid < r) modify(l, r, x, mid+1, R, rt<<1|1);
     37 }
     38 
     39 int solve(int key, int tot, int *arr)
     40 {
     41     int mid;
     42     int l = 0, r = tot-1;
     43     while(l <= r) {
     44         mid = (l+r)>>1;
     45         if(arr[mid] == key) return mid;
     46         if(arr[mid] > key) r = mid-1;
     47         else l = mid+1;
     48     }
     49 }
     50 
     51 void query(int l, int r, int rt)
     52 {
     53     if(lazy[rt] != -1) {
     54         if(vis[lazy[rt]] == 0)
     55             cnt++;
     56         vis[lazy[rt]] = 1;
     57         return;
     58     }
     59     if(l == r) return;
     60     int mid = (l+r)>>1;
     61     query(l, mid, rt<<1);
     62     query(mid+1, r, rt<<1|1);
     63 }
     64 
     65 int main()
     66 {
     67     int i, j, k;
     68     int n, T;
     69     int tot, l, r;
     70     while(scanf("%d", &T) != EOF)
     71     while(T--)
     72     {
     73         memset(vis, 0, sizeof(vis));
     74         memset(lazy, 0xff, sizeof(lazy));
     75         tot = cnt = 0;
     76 
     77         scanf("%d", &n);
     78         for(i = 0; i < n; ++i) {
     79             scanf("%d %d", &l, &r);
     80             if(vis[l] == 0){
     81                 vis[l] = 1;
     82                 s[tot++] = l;
     83             }
     84             if(vis[r] == 0) {
     85                 s[tot++] = r;
     86                 vis[r] = 1;
     87             }
     88             node[i].l = l, node[i].r = r;
     89         }
     90 
     91         sort(s, s+tot);
     92 
     93         for(i = tot-1; i > 0; --i) {
     94             if(s[i] - s[i-1] > 1)
     95                 s[tot++] = s[i-1]+1;
     96         }
     97         sort(s, s+tot);
     98 
     99         for(i = 0; i < n; ++i) {
    100             l = solve(node[i].l, tot, s);
    101             r = solve(node[i].r, tot, s);
    102             modify(l, r, i, 0, tot, 1);
    103         }
    104         memset(vis, 0, sizeof(vis));
    105         query(0, tot, 1);
    106         printf("%d\n", cnt);
    107     }
    108     return 0;
    109 }

     

    题目链接:http://poj.org/problem?id=2528

  • 相关阅读:
    Python脚本模拟登陆DVWA
    PHP单元测试使用
    PHPUnit实践一(初识)
    composer引用本地git做为源库
    编写自己的composer项目
    Laravel 核心--Facades 门面
    Laravel5 创建自定义门面(Facade)
    简单理解laravel框架中的服务容器,服务提供者以及怎样调用服务
    Laravel自带SMTP邮件组件实现发送邮件(QQ、163、企业邮箱都可)
    cocos2d-x游戏开发系列教程-坦克大战游戏之坦克和地图碰撞的检测下
  • 原文地址:https://www.cnblogs.com/Griselda/p/2740527.html
Copyright © 2020-2023  润新知