• BZOJ4237 稻草人 分治 单调栈


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

    题目传送门 - BZOJ4237

    题意

      平面上有$n(nleq 2 imes 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
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    单元測试和白盒測试相关总结
    数据结构:图的实现--邻接矩阵
    Android提示版本号更新操作流程
    《集体智慧编程》代码勘误:第六章
    LINUX设备驱动程序笔记(三)字符设备驱动程序
    数学定理证明机械化的中国学派(II)
    《Java并发编程实战》第三章 对象的共享 读书笔记
    Linux系列-安装经常使用软件
    Kubuntu 初始配置
    虚拟互换(virtual swap)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ4237.html
Copyright © 2020-2023  润新知