• POJ


    其实很早就在白书上的常用技巧 看到离散化的操作,但是之前一直没遇到过需要离散化的题目(应该是我太菜的缘故),所以一直也没怎么重视,下面说说这道题目的考点,也就是离散化

    什么是离散化呢?请先自行百度理解了,一定先了解后再往下看。

    那么该如何进行操作呢?

    举个例子

    假如 我们有5个数

     36   63431  986357  812345678     2147483640 

    很明显  它们的大小关系为   36 < 63431 < 986357  < 812345678 < 2147483640

    但是,我们并不需要知道 36   63431  986357  812345678     2147483640 它们实际的大小,只需要知道它们的相对大小就可以了

    所以我们可以把  36转化为 1  63431转化为2  986357转化为3  812345678 转化为4  2147483640转化为5

    这样我们得到了新的5个数 也就是 1 2 3 4 5

    同时,它们的相对大小还是一样的  1<2<3<4<5 

    再用题目中的数据来举个例子

    1
    5
    1 4
    2 6
    8 10
    3 4
    7 10

    我们得到了5个范围,也就是1~4, 2~6, 8~10, 3~4, 7~10.

    同样的,我们并不需要知道它们的实际范围,只需要知道它们的相对范围就可以了

    我们把它们每个点都整合起来  所以就是   1 2 3 4 4 6 7 8 10 10

    然后去掉重复的点 剩下 1 2 3 4 6 7 8 10

    离散化得到新的范围 1~4,  2~5, 7~8, 3~4, 6~8

    画个图会发现,新的范围 和 旧的范围  的  相对范围,其实是一样的.

    下面是这道题的思路:

      线段树方面是常规操作,关键是这个离散化就有点特殊了

      首先我们测试下这个数据

      1
      3
      1 10
      1 4
      6 10

      会发现常规的离散化会覆盖点5这个点,而得到答案2,但是应该是3才对

      这时候我们需要把每个点的右边的数加入  离散化的操作中来保证 连续性

      (但是这个题目的数据太弱,导致错误的离散化也可以AC)

    #include <algorithm>
    #include <iostream>
    #include<sstream>
    #include<iterator>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<deque>
    #include<map>
    #include<set>
    
    #define M 100005
    #define inf 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    int T, n;
    int x, y, z;
    set<int>ans;
    vector<int>num;
    
    struct Data {
        int l, r, val, lazy;
    }tree[8*M];
    
    struct Data_x {
        int u, v;
    }loc_[M], loc[M];//loc_c是最初的数据,loc是离散后的数据
    
    void built(int l, int r, int k) {
        tree[k].l = l, tree[k].r = r;
        tree[k].val = tree[k].lazy = 0;
        if (l == r)return;
        int mid = (l + r) / 2;
        built(l, mid, k << 1);
        built(mid + 1, r, (k << 1) | 1);
    }
    
    void down(int k) {
        tree[k << 1].val = tree[k << 1].lazy = tree[k].lazy;
        tree[(k << 1) | 1].val = tree[(k << 1) | 1].lazy = tree[k].lazy;
        tree[k].lazy = 0;
    }
    
    void change(int k) {
        if (tree[k].l >= x && tree[k].r <= y) {
            tree[k].val = z;
            tree[k].lazy = z;
            return;
        }
        if (tree[k].lazy)down(k);
        int mid = (tree[k].l + tree[k].r) / 2;
        if (x <= mid)change(k << 1);
        if (y > mid)change((k << 1) | 1);
        if (tree[k << 1].val == tree[(k << 1) | 1].val) tree[k].val = tree[k << 1].val;
        else tree[k].val = -1;
    }
    
    void cal(int k) {
        if (tree[k].val>0) {
            ans.insert(tree[k].val);
            return;
        }
        if (!tree[k].val) return;
        cal(k << 1);
        cal((k << 1) | 1);
    }
    
    int main()
    {
        cin >> T;
        while (T--) {
            cin >> n;
            ans.clear();
            num.clear();
            for (int i = 1; i <= n; i++) {
                scanf("%d%d", &loc_[i].u, &loc_[i].v);//读入最初的数据、
                //把所有的点整合在一起
                num.push_back(loc_[i].u);
                num.push_back(loc_[i].v);
                //保证连续性
                num.push_back(loc_[i].u + 1);
                num.push_back(loc_[i].v + 1);
            }
    
            sort(num.begin(), num.end());
            vector<int>::iterator iter = unique(num.begin(), num.end());//去重
    
            //得到新的范围
            for (int i = 1; i <= n; i++) {
                loc[i].u = lower_bound(num.begin(), iter,loc_[i].u) - num.begin();
                loc[i].v = lower_bound(num.begin(), iter, loc_[i].v) - num.begin();
                loc[i].u++;
                loc[i].v++;
            }
            
            built(1, M, 1);
            for (int i = 1; i <= n; i++) {
                x = loc[i].u, y = loc[i].v, z = i;
                change(1);
            }
            cal(1);
            cout << ans.size() << endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    计算机为什么要从 0 开始计数?
    MySQL索引结构为什么是B+树
    expdp导出报错ORA-39127
    expdp 跳过坏块
    (转)没有索引导致的DIRECT PATH READ
    Python的实用场景有哪些
    Oracle索引修复 ,ORA-00600: internal error code, arguments: [6200],
    CentOS7.6静默安装19C实例脚本 ORA-27125 [FATAL] [DBT-10322]
    ORA-00313: 无法打开日志组
    cursor: pin S wait on X等待事件的处理过程(转载)
  • 原文地址:https://www.cnblogs.com/caibingxu/p/10805640.html
Copyright © 2020-2023  润新知