Luogu3028 solution

Problem

给定 \(n\) 个区间 \([l_i,r_i]\),找到一个点,使之包含它的区间最多。

link->https://www.luogu.com.cn/problem/P3028

Solution

我们将题目换一种方法来理解:给定 \(n\) 个区间 \([l_i,r_i]\) 将其中的每个元素都给 \(+1\),求问最后的所有元素最大值。

是的,聪明的你一下子就看了出来,这是一道裸的差分。

for(int i=1;i<=n;i++) {
	int l,r;
	scanf("%d%d",&l,&r);
	d[l]++; d[r+1]--;
}

但...这样就完了吗?不,我们看见 \(l_i,r_i\le10^9\),数组无疑存不下这么大的空间,就算存的下,我们将 \(0\)\(\max\{r_i\}\) 一一遍历仍会超时。

这是,我们需要使用一种方法叫做离散化,这里不作过多介绍。

Code

#include<bits/stdc++.h>
#define pd push_back
#define pb pop_back
#define mk make_pair
//#define int long long
#define PII pair<int,int>
#define _for(a,b,c) for(int a=b;a<=c;a++)
#define _rep(a,b,c) for(int a=b;a>=c;a--)
using namespace std;
template <typename T> inline void read(T& x) {
	x=0; T f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch&15); ch=getchar(); }
	x=x*f;
	return;
}
template <typename T,typename ...Arg> inline void read(T& x,Arg& ...arg){
	read(x); read(arg...);
}
int power(int a,int b) {
	int ans=1;
	do {
		if(b&1) ans*=a; a*=a;
	} while(b>>=1);
	return ans;
}
const int N=1e5+5;
int d[N],l[N],r[N],v[N],tot,n,ans;
signed main() {
	read(n);
	_for(i,1,n)
		read(l[i],r[i]),v[++tot]=l[i],v[++tot]=r[i];
	sort(v+1,v+tot+1); //排序
	tot=unique(v+1,v+tot+1)-(v+1); //去重
	_for(i,1,n) {
//		printf("(%d,%d)+=1\n",lower_bound(v+1,v+tot+1,l[i])-v,lower_bound(v+1,v+tot+1,r[i])-v);
		++d[lower_bound(v+1,v+tot+1,l[i])-v],--d[lower_bound(v+1,v+tot+1,r[i])-v+1]; //将离散化后的 l[i]~r[i] 区间+1
	}
	_for(i,1,tot+1)
		ans=max(ans,d[i]+=d[i-1]); //做前缀和,还原数组
	printf("%d",ans);
	return 1;
}

posted @ 2022-08-01 14:04  lsj2009  阅读(32)  评论(0)    收藏  举报