BZOJ4237 稻草人 分治 单调栈

原文链接https://www.cnblogs.com/zhouzhendong/p/8682572.html

题目传送门 - BZOJ4237

题意

  平面上有$n(n\leq 2\times 10^5)$个整点(坐标范围在$[0,10^9]$之间)。

  第$i$个点$p_i$的坐标是$(x_i,y_i)$。

  如果有一对点$p_i$和$p_j$,满足$x_i<x_j,y_i<y_j$,而且以这两个点为左下角和右上角所围城的矩形内不包含任何整点(边界上面不算),那么他们对答案的贡献为1。

  求答案。

题解

  对于$x$坐标分治,然后单调栈解决跨越中线两端的点的贡献即可。

  好像听好写的,不详细介绍了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005;
struct Point{
	int x,y;
	void get(){
		scanf("%d%d",&x,&y);
	}
}p[N],q[N];
int n,Lstack[N],Rstack[N],Ltop,Rtop;
LL ans=0;
bool cmpx(Point a,Point b){
	return a.x<b.x;
}
void solve(int xL,int xR,int L,int R){
	if (L>=R)
		return;
	int xmid=(xL+xR)>>1,mid=R;
	while (mid>=L&&p[mid].x>xmid)
		mid--;
	solve(xL,xmid,L,mid);
	solve(xmid+1,xR,mid+1,R);
	Ltop=Rtop=0;
	Lstack[0]=Rstack[0]=0;
	q[0].y=-1;
	for (int i=L,l=L,r=mid+1;i<=R;i++)
		if (r>R||(l<=mid&&p[l].y<=p[r].y)){
			q[i]=p[l++];
			while (Ltop>0&&q[Lstack[Ltop]].x<q[i].x)
				Ltop--;
			Lstack[++Ltop]=i;
	/*		int pos=Ltop,y;
			for (int j=1<<18;j>0;j>>=1)
				if (pos-j>0&&q[Lstack[pos-j]].x==q[i].x)
					pos-=j;
			y=q[Lstack[pos-1]].y+1;
			pos=Rtop+1;
			for (int j=1<<18;j>0;j>>=1)
				if (pos-j>0&&q[Rstack[pos-j]].y>=y)
					pos-=j;
			ans+=Rtop-pos+1;*/
		}
		else {
			q[i]=p[r++];
			while (Rtop>0&&q[Rstack[Rtop]].x>q[i].x)
				Rtop--;
			Rstack[++Rtop]=i;
			int pos=Rtop,y;
			for (int j=1<<18;j>0;j>>=1)
				if (pos-j>0&&q[Rstack[pos-j]].x==q[i].x)
					pos-=j;
			y=q[Rstack[pos-1]].y+1;
			pos=Ltop+1;
			for (int j=1<<18;j>0;j>>=1)
				if (pos-j>0&&q[Lstack[pos-j]].y>=y)
					pos-=j;
			ans+=Ltop-pos+1;
		}
	for (int i=L;i<=R;i++)
		p[i]=q[i];
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		p[i].get();
	sort(p+1,p+n+1,cmpx);
	solve(0,1e9,1,n);
	printf("%lld\n",ans);
	return 0;
}

  

posted @ 2018-03-31 15:48  zzd233  阅读(267)  评论(0编辑  收藏  举报