Study notes: Discretization

Discretization is to map a finite individual in an infinite space to a finite space to improve the space-time efficiency of the algorithm. In layman's terms, discretization is to reduce the data accordingly without changing the relative size of the data.

Look at an example:
AcWing 802. Interval and

Suppose there is an infinite number line, and each coordinate on the number line is 0.

Now, we first perform n operations, and each operation adds c to the number at a certain position x.

Next, make m queries. Each query contains two integers l and r. You need to find the sum of all the numbers in the interval [l, r].
(-1e9 <= x,l,r <= 1e9, 1 <= n,m <= 1e5, -1e4 <= c <= 1e4)

Practice: It
can be seen that we cannot simply use coordinates as array subscripts, because the range of coordinates is very large, and the array cannot be opened so large, but we found that although the range of coordinates is very large, the number of coordinates used is limited. Because there are only (m+n) queries at most, even if a different coordinate is used for each query, at most 3e5 different coordinates will be used. This range is acceptable.
So the method is to discretize the coordinates, and finally Use the prefix and process it again, output the answer

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#define endl '\n'
#include<algorithm>
using namespace std;

inline ll read()
{
    
    
	ll x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9')	{
    
     if(ch=='-') f=-1; ch=getchar(); }
	while('0'<=ch&&ch<='9')	x=x*10+ch-'0', ch=getchar();
	return f*x;
}

const int maxn = 3e5+5;

int n,m;
int a[maxn],s[maxn];

vector<int> alls;//存放待离散化的坐标 
vector<pair<int,int> > add,query;//存放添加操作与询问操作 

int find(int x)//查找坐标x离散化后对应的数组下标 
{
    
    
	int l=-1,r=alls.size();
	while(l+1!=r)//二分查找 
	{
    
    
		int mid=l+r>>1;
		if(alls[mid]>=x)	r=mid;
		else	l=mid;
	}
	return r+1;//将x映射到1,2...n 
	// 如果 return r; 是映射到 0,1,2... 
}

int main()
{
    
    
	cin>>n>>m;
	//先将所有用到的坐标存进去 
	for(int i=0;i<n;i++)
	{
    
    
		int x,c;
		cin>>x>>c;
		
		alls.push_back(x);
		add.push_back(m_p(x,c));
	}
	for(int i=0;i<m;i++)
	{
    
    
		int l,r;
		cin>>l>>r;
		
		alls.push_back(l); alls.push_back(r);
		query.push_back(m_p(l,r));
	}
	
	// 排序 + 去重 
	sort(alls.begin(),alls.end());
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	
	//处理添加操作 
	for(int i=0;i<n;i++)
	{
    
    
		int pos=find(add[i].first);
		a[pos]+=add[i].second; 
	}
	
	//对数组a进行前缀和处理
	for(int i=1;i<=alls.size();i++)	s[i]=s[i-1]+a[i];
	
	//处理查询操作
	for(int i=0;i<m;i++)
	{
    
    
		int l=find(query[i].first), r=find(query[i].second);
		cout<<s[r]-s[l-1]<<endl;
	}
	return 0;
}

y Total 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
}

作者:yxc
来源:AcWing

Guess you like

Origin blog.csdn.net/m0_50815157/article/details/113481523