Fundamental Algorithms: Basic Applications of Discretization

Discretization is often used to clear a large space, but the actual space used is very small. Suppose an array of arr[100010] is opened, but only 10,000 are actually used. At this time, discretization can be used.

 Discretization template:

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
}

The unique function removes adjacent duplicate elements in an array. However, its essence is to move the repeated elements to the end of the array, and finally point the end of the iterator to the subscript of the first repeated element. For example, the original array is 1 1 2 2 3 4 5 5 6 6. After unique, the same elements as 1 2 3 4 5 6 will be placed after 6, and the unique function returns the address of 6, so pass Erase function, delete all the numbers from 6 to alls.end( )

Classic example:

 Topic idea:

First map the interval, find the corresponding interval, add c to the corresponding interval, and find the prefix sum. The sum of a certain interval can be obtained by s[r]-s[l-1]

AC code:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef pair<int, int> PII;//pair为讲两个数据合成一组数据
const int N = 30010;
int n, m;
int a[N], s[N];
//s[N]用于求前缀和
//a[N]用于记录离散化后对应区间+c(操作之后)的数值
vector<int>alls;//存所有的区间
vector<PII>add, query;//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;//映射为1,2,3,4,5,6,所以需要加1
	//如果return r; 则映射为0,1,2,3,4,5
}

int main(void) {
	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) {//将add的值一个个复制给item
		//add有两个值(A,B),first取的A,second取的B
		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) {//将query的值一个个复制给item
		//找到离散化后的l和r进行求区间和
		int l = find(item.first), r = find(item.second);
		cout << s[r] - s[l - 1] << endl;
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/AkieMo/article/details/128029492