Notas de estudio: discretización

La discretización consiste en mapear un individuo finito en un espacio infinito a un espacio finito para mejorar la eficiencia espacio-temporal del algoritmo. En términos sencillos, la discretización consiste en reducir los datos en consecuencia sin cambiar el tamaño relativo de los datos.

Mire un ejemplo:
AcWing 802. Intervalo y

Suponga que hay una recta numérica infinita y cada coordenada en la recta numérica es 0.

Ahora, primero realizamos n operaciones, y cada operación suma c al número en una determinada posición x.

A continuación, haz m consultas. Cada consulta contiene dos números enteros ly r. Necesitas encontrar la suma de todos los números en el intervalo [l, r].
(-1e9 <= x, l, r <= 1e9, 1 <= n, m <= 1e5, -1e4 <= c <= 1e4)

Práctica: Se
puede ver que no podemos simplemente usar coordenadas como subíndices de matriz, porque el rango de coordenadas es muy grande y la matriz no se puede abrir tan grande, pero encontramos que aunque el rango de coordenadas es muy grande, el número de Las coordenadas utilizadas son limitadas. Debido a que solo hay (m + n) consultas como máximo, incluso si se utiliza una coordenada diferente para cada consulta, se utilizarán como máximo 3e5 coordenadas diferentes. Este rango es aceptable.
Por lo tanto, el método es discretizar el coordenadas, y finalmente use el prefijo y proceselo nuevamente, genere la respuesta

#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 Plantilla de discretización total:

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

Supongo que te gusta

Origin blog.csdn.net/m0_50815157/article/details/113481523
Recomendado
Clasificación