離散化

離散化的步驟:

1、去重---數列中可能存在重複元素

2、二分查找---算出x離散化的值

vector<int> alls; // 存儲所有待離散化的值
sort(alls.begin(), alls.end()); // 將所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end());   // 去掉重複元素

// 二分求出x對應的離散化的值
int find(int x) // 找到第一個大於等於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; // 映射到1, 2, ...n
}

例題:區間和

假定有一個無限長的數軸,數軸上每個座標上的數都是0。

現在,我們首先進行 n 次操作,每次操作將某一位置x上的數加c。

近下來,進行 m 次詢問,每個詢問包含兩個整數l和r,你需要求出在區間[l, r]之間的所有數的和。

輸入格式

第一行包含兩個整數n和m。

接下來 n 行,每行包含兩個整數x和c。

再接下里 m 行,每行包含兩個整數l和r。

輸出格式

共m行,每行輸出一個詢問中所求的區間內數字和。

數據範圍

-10^9\leq x\leq 10^9, 1\leq n,m\leq 10^5, -10^9\leq l\leq r\leq 10^9, -10000\leq c \leq 10000

輸入樣例:

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

輸出樣例:

8
0
5
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 3e5+10;
int A[N],sum[N];
vector<int>alls;
vector<pair<int,int> >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;
    for(int i=0;i<n;i++){
        int x,c;
        cin>>x>>c;
        add.push_back({x,c});

        alls.push_back(x);
    }
    for(int i=0;i<m;i++){
        int l,r;
        cin>>l>>r;
        query.push_back({l,r});

        alls.push_back(l);
        alls.push_back(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++)
        sum[i]=sum[i-1]+A[i];
    //處理詢問
    for(auto item:query){
        int l=Find(item.first),r=Find(item.second);
        cout<<sum[r]-sum[l-1]<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章