zoukankan      html  css  js  c++  java
  • BZOJ4237稻草人——单调栈+CDQ分治

    题目描述

    JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典。
    有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地。和启示中的一样,田地需要满足以下条件:
    田地的形状是边平行于坐标轴的长方形;
    左下角和右上角各有一个稻草人;
    田地的内部(不包括边界)没有稻草人。
    给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数

    输入

    第一行一个正整数N,代表稻草人的个数
    接下来N行,第i行(1<=i<=N)包含2个由空格分隔的整数Xi和Yi,表示第i个稻草人的坐标

    输出

    输出一行一个正整数,代表遵从启示的田地的个数

    样例输入

    4
    0 0
    2 2
    3 4
    4 3

    样例输出

    3

    提示 

    所有满足要求的田地由下图所示:

     
    1<=N<=2*10^5
    0<=Xi<=10^9(1<=i<=N)
    0<=Yi<=10^9(1<=i<=N)
    Xi(1<=i<=N)互不相同。
    Yi(1<=i<=N)互不相同。
     
    二维平面问题,将一维排序用$CDQ$分治解决,然后变为序列问题。将纵坐标$CDQ$分治,每次将区间内的点分为两部分,考虑右上角在上半部分,左下角在下半部分的贡献。对于上半部分维护单调递增的单调栈,对于下半部分维护单调递减的单调栈,这样对于上面每个点在下面的单调栈中二分即可得到贡献。
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int mod=998244353;
    struct lty
    {
    	int x,y;
    }q[200010];
    int up[200010];
    int t1,t2,n;
    int down[200010];
    ll ans;
    bool cmp1(lty a,lty b)
    {
    	return a.y<b.y;
    }
    bool cmp2(lty a,lty b)
    {
    	return a.x<b.x;
    }
    int find(int val)
    {
    	int l=1,r=t2;
    	if(t2==0)return 0;
    	int res=-1;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(q[down[mid]].x>val)
    		{
    			r=mid-1;
    			res=mid;
    		}
    		else
    		{
    			l=mid+1;
    		}
    	}
    	if(res==-1)return 0;
    	return t2-res+1;
    }
    void CDQ(int l,int r)
    {
    	if(l==r)return ;
    	int mid=(l+r)>>1;
    	sort(q+l,q+r+1,cmp1);
    	sort(q+l,q+mid+1,cmp2);
    	sort(q+mid+1,q+r+1,cmp2);
    	t1=t2=0;
    	int num=l;
    	for(int i=mid+1;i<=r;i++)
    	{
    		while(t1&&q[i].y<=q[up[t1]].y)
    		{
    			t1--;
    		}
    		up[++t1]=i;
    		while(q[num].x<q[i].x&&num<=mid)
    		{
    			while(t2&&q[num].y>=q[down[t2]].y)
    			{
    				t2--;
    			}
    			down[++t2]=num;
    			num++;
    		}
    		ans+=find(q[up[t1-1]].x);
    	}
    	CDQ(l,mid),CDQ(mid+1,r);
    }
    int main()
    {
    	scanf("%d",&n);
    	q[0].x=q[0].y=-1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&q[i].x,&q[i].y);
    	}
    	CDQ(1,n);
    	printf("%lld",ans);
    }
  • 相关阅读:
    离线下载使用Google商店插件crx
    springboot thymeleaf 引入js
    如何保证系统重启,tomcat自动重启
    如何实现财务自由
    理财之道
    九大职场定律
    算法系列二:如何学习算法
    FastDFS结合Flask使用
    系统权限的实现
    正则表达式
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10982046.html
Copyright © 2011-2022 走看看