离散化-算法运算-模板

适用条件

适用于值域比较大 -1e9 <= x <= 1e9
但是个数比较少 n <= 1e5

离散化的作用机理

d[]:  			 1			3			100			1500

映射              |	        |            |            |

                  0         1            2            3

出现的问题

一/ d[] 中可能有重复元素
二/ 如何算出x 离散化后对应的值是多少

针对以上问题:
1.首先要去重
2.把其转化为有序序列,可用二分法来找

模板

vector<int>  alls //储存待离散化的值

sort(alls.begin(),alls.end()) // 排序

alls.erase(unique(alls.begin(),alls.end()),alls.end()) //去重

find(x) 找出x对应的下标


例题

/求区间和 给定一个无限长的数轴,数轴上每个坐标都是0, -1e9 - 1e9 首先进行n 次操作
每次操作将某一个位置x上的数加上 C
接下来进行 M次询问,你需要求出区间[l,r]之间的所有数之和;
/

/*
输入格式
第一行 包含 n m 两个整数
接下来 n行 每行包含两个整数 x 和 c
在接下来m行 每行包含两个整数 l 和 r

输出格式
共m行 每行输出一个询问中所求的区间内的数字和

数据范围
-1e9 <= x <= 1e9
1 <= n,m <=1e5
-1e9 <= l,r <= 1e9
-10000 <= c <= 10000
*/

#include <bits/stdc++.h>

using namespace std;


const int N = 3e5 + 10;

typedef pair<int, int> PII;

int n, m, x, c, l, r;

vector<PII> add, getlr;
vector<int> alls;
int a[N], s[N];
int find(int x)
{
	int l = 0, r = alls.size() - 1;
	while (l < r)
	{
		int mid = l + r + 1>> 1;
		if (alls[mid] <= x) l = mid;
		else r = mid - 1;
	}
	
	return r + 1; //因为是前缀和,所以下标要从1开始 
}
int main()
{
	cin >> n >> m;
	while (n --)
	{
		cin >> x >> c;
		add.push_back({x, c});
		alls.push_back(x);
	}
	for(int i = 0; i < m; i ++)
	{
		cin >> l >> r;
		getlr.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 seg : add)
	{
		int idx = find(seg.first);
		a[idx] += seg.second;
	} 
	for (int i = 1; i <= alls.size(); i ++) s[i] = s[i - 1] + a[i];
	for (auto seg : getlr)
	{
		l = find(seg.first);
		r = find(seg.second);
		cout << s[r] - s[l - 1] << endl; 
	 } 
     system("pause");
	return 0;
}
 

猜你喜欢

转载自blog.csdn.net/FRANK48691/article/details/107523756