离散化

区间和:

#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个区间。

 

posted @ 2020-04-08 11:39  龙雪可可  阅读(120)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************