题意 : 在墙上贴海报, n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。求出最后还能看见多少张海报。

分析 : 很容易想到利用线段树来成段置换,最后统计总区间不同数的个数。但是这里有一个问题,就是区间可以很大,线段树开不了那么大的空间,遂想能不能离散化。实际上只记录坐标的相对大小进行离散化最后是不影响我们计算的,但是光是普通的离散化是不行的,就是我们贴海报的实际意义是对(l, r)段进行添加,而不是对于这个区间的点进行添加,是段树不是点树,如果这样普通离散化的话就会出现一个问题,比如数据1-10、1-4、6-10 行的,我们离散化后是1-4、1-2、3-4 ,不离散的结果是 3 但是离散化后再计算就是 2 了!原因就是我们是成段更新而不是点更新,进行添加海报的(l, r)的意义是对这一段进行添加,而离散化之后将原本不相邻的点变成了相邻的点,就导致了上面例子 4 - 6被覆盖了!解决这个问题的方法就是,在离散化的时候,将原本不相邻的两个点中间添加一个数,来表示中间是有“缝隙”的。

另外说一下 : POJ上的数据弱了,所以可能离散化的时候没有注意这个问题也能AC,可以去discuss板块里面看看大牛们的数据

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
;
struct Interval{ int L, R; };
Interval Sec[maxn>>];
];
];
bool vis[maxn];
int ans;
void PushDown(int rt) {
       if (col[rt]) {
              col[rt<<] = col[rt<<|] = col[rt];
              col[rt] = ;
       }
}
void query(int l, int r, int rt)
{
    if(col[rt]){//下面的这一段都是 col[rt] 了, 所以不必再往下更新
        if(!vis[col[rt]]) ans++;
        vis[col[rt]] = true;
        return ;
    }
    if(l == r) return;
    ;
    query(lson);
    query(rson);
}
void update(int L,int R,int c,int l,int r,int rt) {
       if (L <= l && r <= R) {
              col[rt] = c;
              return ;
       }
       PushDown(rt);
       ;
       if (L <= m) update(L , R , c , lson);
       if (R > m) update(L , R , c , rson);
}
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        ;
        memset(col, , sizeof(col));
        memset(vis, false, sizeof(vis));

        scanf("%d", &n);
        ; i<n; i++){
            scanf("%d %d", &Sec[i].L, &Sec[i].R);
            arr[top++] = Sec[i].L, //记录所有出现的点
            arr[top++] = Sec[i].R;
        }

        sort(arr, arr+top);
        top = unique(arr, arr+top) - arr;//将点去重

        ; i>; i--){
            ] + )//在原本不相邻的点中间添加一个数,因为后面是要sort的,所以添加在数组末尾即可
                arr[top++] = arr[i-] + ;//要做到这个操作只要从后往前判断就可以了,或者一开始把top的值记下来也行
        }

        sort(arr, arr+top);

        ans = ;
        ; i<n; i++){
            int l = lower_bound(arr, arr+top, Sec[i].L) - arr;//在离散化之后的坐标系arr中寻找左端点
            int r = lower_bound(arr, arr+top, Sec[i].R) - arr;//寻找右端点

            update(l+, r+, i+, , top, );//更新,注意离散化之后的坐标是从0开始的,这里我们把坐标人为+1进行计算
        }
        query(, top, );//查询整个区间统计不同数的个数
        printf("%d\n", ans);
    }
    ;
}

瞎 :对于线段树模版不能硬套,要结合题目对于模版进行适当的修改才能更好发挥这个数据结构的威力!例如这题的查询操作,在查询的时候提前判断下面是否都是一样的数了这个操作,如果死套模版,可能就是单点查询存数组再去unique判断,这个是很不明智的!

最新文章

  1. HTML5进阶段内联标签汇总(小篇)
  2. try-catch
  3. jQuery 表格删除,添加行
  4. RPC原理详解
  5. 使用Apache Archiva搭建Maven Repository Server
  6. Shiro-密码的MD5加密
  7. android 给空白包签名
  8. HTML 5 应用程序缓存
  9. 20145236 《Java程序设计》实验三实验报告
  10. HiveSQL解析过程详解 | 学步园
  11. HUST 1017 Exact cover dance links
  12. infopath 之绑定列表 数据源
  13. HTML5 Canvas核心技术—图形、动画与游戏开发.pdf6
  14. day-7
  15. cocos2d-3.x 创建动画
  16. P Invoke struct结构
  17. log4net 单独项目
  18. 怎么修改TOMCAT的默认主页为你自己项目的主页
  19. dive 方便的观察容器各层信息的工具
  20. windows下安装apache zookeeper

热门文章

  1. 【VS开发】DLL和ocx的区别
  2. 小记----采集之Xpath
  3. Luogu P4602 [CTSC2018]混合果汁
  4. mybatis中foreach的用法以及特殊的情况的用法
  5. Elasticsearch入门教程(一):Elasticsearch及插件安装
  6. ExpressionToSQL
  7. Hadoop基础概念
  8. 关于python3.4版本中的zip函数
  9. 需求文档(PRD文档)
  10. python接口自动化 - Requests-3 高级用法