B - Beam Cannon(扫描线)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B - Beam Cannon(扫描线)相关的知识,希望对你有一定的参考价值。

B - Beam Cannon (扫描线)

求给定 w × h w\\times h w×h的矩形覆盖的最多的点数。

经典扫描线。

对一个点建立两条边,一条入边(x,y,y+h)权为1,一条出边(x+w,y,y+h)权为-1。

然后用线段树维护y,每次查询整个区间的max即可。

这里我们枚举的是矩形的右上角,显然对于一个点 ( x , y ) (x,y) (x,y)

( x , y ) (x,y) (x,y) ( x + w , y + h ) (x+w,y+h) (x+w,y+h)这个矩形的所有范围都可以作为右上角包括该点。

而边的权就是控制 x x x轴,线段树 y y y就是维护答案。

因此本题只需写一个,区间更新,查询就是 a 1 . s u m a_1.sum a1.sum即可。

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

// Problem: B - Beam Cannon
// Contest: Virtual Judge - [练习]2014上海全国邀请赛——题目重现 [Cloned]
// URL: https://vjudge.net/contest/466761#problem/B
// Memory Limit: 65 MB
// Time Limit: 1500 ms
// Date: 2021-11-04 15:53:00
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = {402653189,805306457,1610612741,998244353};
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
//区间修改 区间求和
#define il inline 
#define lx x<<1
#define rx x<<1|1
#define len(x) (a[x].r-a[x].l+1)
struct SegTree{
	struct node{
	int l,r,lz;
	int s;
	}a[(2*M)<<2];
	il void re(int x){ a[x].s=max(a[lx].s,a[rx].s); }
	il void ptg(int x,int y){
		a[x].lz+=y;
		a[x].s+=y;
	}
	il void pd(int x){
		if(a[x].lz){
			ptg(lx,a[x].lz),ptg(rx,a[x].lz);
			a[x].lz=0;
		}
	}
	il void bud(int x,int l,int r){
		a[x].l=l,a[x].r=r;
		a[x].s=a[x].lz=0;
		if(l==r){
			//scanf("%d",&a[x].s);
			return;
		}
		int m=(l+r)>>1;bud(lx,l,m),bud(rx,m+1,r);
		re(x);
	}
	il void upd(int x,int l,int r,int val){
		if(a[x].l>=l&&a[x].r<=r){
			ptg(x,val);return;
		}
		pd(x);
		int m=(a[x].l+a[x].r)>>1;
		if(l<=m) upd(lx,l,r,val);
		if(r>m) upd(rx,l,r,val);
		re(x);
	}
	il int que(int x,int l,int r){
		if(a[x].l>=l&&a[x].r<=r) return a[x].s;
		pd(x);
		int m=(a[x].l+a[x].r)>>1;int ans=0;
		if(l<=m) ans+=que(lx,l,r);
		if(r>m) ans+=que(rx,l,r);
		return ans;
	}
}T;
struct node{
	int x,y,v;
	bool operator< (const node &a)const{
		return a.x==x?v>a.v:x<a.x;
	}
}a[N<<1];
int main(){
	int n,w,h;
	while(~scanf("%d",&n)){
		if(n<0) break;
	scanf("%d%d",&w,&h);
	rep(i,1,n){
		int j=(i<<1)-1;
		scanf("%d%d",&a[j].x,&a[j].y);
		a[j].v=1;
		a[j].y+=M;
		a[j+1]=a[j];a[j+1].x+=w;
		a[j+1].v=-1;
	}
	n<<=1;
	sort(a+1,a+n+1);
	int ans=0;
	T.bud(1,1,2*M);
	rep(i,1,n){
		T.upd(1,a[i].y,a[i].y+h,a[i].v);
	//	printf("%d %d\\n",a[i].x,a[i].v);
		ans=max(ans,T.a[1].s);
	}
	printf("%d\\n",ans);
	}
	return 0;
}

以上是关于B - Beam Cannon(扫描线)的主要内容,如果未能解决你的问题,请参考以下文章

HDOJ 5091 Beam Cannon 扫描线

贪心小Y的炮[cannon]题解

ae特效里cannon是啥意思

三星开发者大会搬入日本Cannon Tokki的蒸镀机和Cannon的曝光机

[USACO18DEC]Balance Beam

Android zxing Journeyapps 条码扫描器内部片段