周赛D. Digging for Gold(扫描线)

给出二维平面上的一些点。

询问一个\(K\times K\)的正方形,最多能覆盖多少点。

做法:

考虑这个正方形的一个角。这个角确定了,正方形也就确定了。

对于一个点,合法的角的坐标范围形成了一个矩形。

问题转化为,求一些矩形的最大重合点是多少。

扫描线即可。

时间复杂度O(nlogn)。

//对一个点(x,y)来说
//一个矩形内的点是合法的
//那就二维差分
//
//对每个(x,y)对应一个矩形
//求这些矩形的最大覆盖点 
//用扫描线
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m,k;
int t[maxn],mm;
struct {
	pair<int,int> p[4];
	//e表示矩形的长 
}jx[maxn];
 
struct qnode {
	int l,r,v;
};
vector<qnode> g[maxn];
 
int c[maxn<<2],lz[maxn<<2];
void pushdown (int i,int l,int r) {
	int mid=(l+r)>>1;
	if (lz[i]) {
		c[i<<1]+=lz[i];
		lz[i<<1]+=lz[i];
		c[i<<1|1]+=lz[i];
		lz[i<<1|1]+=lz[i];
		lz[i]=0;
	}
}
void up (int i,int l,int r,int L,int R,int v) {
	if (l>=L&&r<=R) {
		c[i]+=v;
		lz[i]+=v;
		return;
	}
	pushdown(i,l,r);
	int mid=(l+r)>>1;
	if (L<=mid) up(i<<1,l,mid,L,R,v);
	if (R>mid) up(i<<1|1,mid+1,r,L,R,v);
	c[i]=max(c[i<<1],c[i<<1|1]); 
}
map<pair<int,int> ,int> mp;
int gg[200][200];
int main () {
	scanf("%d%d%d",&n,&m,&k);
	if (k==1) {
		int ans=0;
		while (m--) {
			int x,y;
			scanf("%d%d",&x,&y);
			mp[{x,y}]++;
			ans=max(ans,mp[{x,y}]);
		}
		printf("%d\n",ans);
		return 0;
	}
	for (int i=1;i<=m;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		jx[i].p[0]={x-k+1,y-k+1};
		jx[i].p[1]={x,y-k+1};
		jx[i].p[2]={x,y};
		jx[i].p[3]={x-k+1,y};
		for (int j=0;j<4;j++) {
			//printf("%d: %d %d\n",i,jx[i].p[j].first,jx[i].p[j].second);
			t[++mm]=jx[i].p[j].first;
			t[++mm]=jx[i].p[j].second;
		}
	}
	sort(t+1,t+mm+1);
	mm=unique(t+1,t+mm+1)-t-1;
	for (int i=1;i<=m;i++) {
		for (int j=0;j<4;j++) {
			jx[i].p[j].first=upper_bound(t+1,t+mm+1,jx[i].p[j].first)-t-1;
			jx[i].p[j].second=upper_bound(t+1,t+mm+1,jx[i].p[j].second)-t-1;
		}
//		for (int j=jx[i].p[0].first;j<=jx[i].p[1].first;j++) {
//			for (int kk=jx[i].p[0].second;kk<=jx[i].p[2].second;kk++) {
//				gg[j][kk]++;
//			}
//		}
	}
//	for (int i=1;i<=mm;i++) {
//		for (int j=1;j<=mm;j++) {
//			printf("%d ",gg[i][j]);
//		}
//		puts("");
//	}
//	return 0;
	for (int i=1;i<=m;i++) {
		g[jx[i].p[0].first].push_back({jx[i].p[0].second,jx[i].p[3].second,1});
		g[jx[i].p[1].first+1].push_back({jx[i].p[1].second,jx[i].p[2].second,-1});
	}
	int ans=0;
	for (int i=1;i<=mm;i++) {
		for (qnode it:g[i]) {
			int l=it.l;
			int r=it.r;
			int v=it.v;
			//printf("%d %d %d %d\n",i,l,r,v);
			up(1,1,mm,l,r,v);
		}
		//printf("%d\n",c[1]); 
		ans=max(ans,c[1]);
	}
	printf("%d\n",ans);
} 
/*
1000000000 4 1000000000
1000000000 1000000000
1000000000 1
1 1000000000
1 1
*/
上一篇:基于Redis的Zset实现用户n分钟内的广告奖励总数——滑动窗口问题


下一篇:838. 推多米诺 —— 2022.2.21