zoukankan      html  css  js  c++  java
  • 离散化

    区间和:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 300000;
    int a[N],s[N];
    typedef pair<int, int> PII;
    vector<int> alls;
    vector<PII> add,query;
    int find(int x)
    {
        int l = 0, r = alls.size()-1;
        while(l<r)
        {
            int mid = l + r >> 1;
            if(alls[mid] >= x) r = mid;
            else l = mid + 1;
        }
        return r + 1;
    }
    int main()
    {
        int n,m;
        cin>>n>>m;
        while(n--)
        {
            int x,c;
            cin>>x>>c;
            alls.push_back(x);
            add.push_back({x,c});
        }
        while(m--)
        {
            int l,r;
            cin>>l>>r;
            alls.push_back(l);
            alls.push_back(r);
            query.push_back({l,r});
        }
        sort(alls.begin(), alls.end());
        alls.erase(unique(alls.begin(), alls.end()), alls.end());
        
        for(auto item : add)
        {
            int x = find(item.first);
            a[x] += item.second;
        }
        for(int i = 1;i<=alls.size();i++) s[i] = s[i-1] + a[i];
        for(auto item : query)
        {
            int l = find(item.first), r = find(item.second);
            cout<<s[r] - s[l-1]<<endl;
        }
    }

     将原来2 * 10^9的数量级离散化成3*10^5,

    x   c          l   r

    1   2          1   3

    3   6          4   6

    7   5          7   8

    alls: 1 3 7 1 3 4 6 7 8

    sort: 1 1 3 3 4 6 7 7 8

    去重:1 3 4 6 7 8  --->x

    把add里面的second变量加到数组里面来,接着结合前缀和的知识,求出前缀和。

    PS:二分查找里面find返回的是第一个大于等于x的位置再+1,因为前缀和要从1开始,即s[i] = s[i-1] + a[i];

    2、区间合并:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 100010;
    typedef pair<int, int> PII;
    vector<PII> segs;
    void merge(vector<PII> &segs)
    {
        vector<PII>res;
        sort(segs.begin(), segs.end());
        int st = -2e9, ed = -2e9;
        for(auto seg : segs)
        {
            if(ed < seg.first)
            {
                if(ed != -2e9) res.push_back({st,ed});
                st = seg.first, ed = seg.second;
            }
            else
            {
                ed = max(ed,seg.second);
            }
        }
        if(ed != -2e9) res.push_back({st,ed});
        segs = res;
    }
    int main()
    {
        int n;
        cin>>n;
        while(n--)
        {
            int l,r;
            cin>>l>>r;
            segs.push_back({l,r});
        }
        merge(segs);
        cout<<segs.size()<<endl;
    }
    5
    1 2
    2 4
    5 6
    7 8
    7 9

    可以将这个样例进行模拟一下:
    1、st = -2e9, ed = -2e9;
    2、ed < 1, 这里只是将维护的区间改为:st = 1, ed = 2;
    3、ed >= 2, 那么ed = max(2,4) = 4, st = 1, ed = 4;区间变为<1,4>
    4、因为st = 4 < 5, 加入区间到结果里面<1,4>, st = 5, ed = 6;
    5、6 < 7, <1,4> <5,6>, st = 7, ed = 8;
    6、st = 7 , ed = max(8,9) = 9;
    7、退出for循环之后还要将剩下的维护区间加进结果里面来:<1,4> <5,6> <7,9>,一共3个区间。

  • 相关阅读:
    jedis scan实现keys功能
    java简单实现一个阻塞式线程池
    Swift运算符
    数组的使用(1)
    Linux 常用命令
    Task02:基础查询与排序
    Task01:初识数据库
    摩尔投票法
    面向对象暑期课程总结
    xpath+requests+peewee——CSDN论坛全方位爬虫
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12658886.html
Copyright © 2011-2022 走看看