zoukankan      html  css  js  c++  java
  • Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】

    正题

    题目链接:https://loj.ac/problem/2880


    题目大意

    给出平面上的(n)个点,然后求有多少个矩形满足

    1. 左下角和右上角各有一个点
    2. 矩形之间没有其他点

    (1leq nleq 2 imes 10^5,1leq x_i,y_ileq 10^9,)保证(x_i,y_i)分别不重复出现。


    解题思路

    按照(x)排序,考虑(CDQ)分治后左边对右边的影响,对(y)从大到小排序然后左右各自维护一个单调栈,左边考虑每个点第一个右上角的点,右边维护一个(y)轴递减,(x)轴递增的单调栈,然后再右边的单调栈上二分出左边的合法位置即可。

    时间复杂度(O(nlog^2 n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=2e5+10;
    struct node{
    	int x,y;
    }p[N];
    int n,s[N],t[N];
    long long ans;
    bool cmp(node x,node y){return x.x<y.x;}
    bool cMp(node x,node y){return x.y>y.y;}
    void CDQ(int l,int r){
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	CDQ(l,mid);
    	CDQ(mid+1,r);
    	sort(p+l,p+mid+1,cMp);
    	sort(p+mid+1,p+r+1,cMp);
    	int z=mid+1,top=0,toq=0;
    	for(int i=l;i<=mid;i++){
    		while(z<=r&&p[z].y>=p[i].y){
    			while(top>0&&p[z].x<p[s[top]].x)top--;
    			s[++top]=z;z++;
    		}
    		while(toq>0&&p[i].x>p[t[toq]].x)toq--;
    		if(toq){
    			int L=1,R=top;
    			while(L<=R){
    				int mid=(L+R)>>1;
    				if(p[s[mid]].y>p[t[toq]].y)L=mid+1;
    				else R=mid-1;
    			}
    			ans+=top-L+1;
    		}
    		else ans+=top;
    		t[++toq]=i;
    	}
    	return;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&p[i].x,&p[i].y);
    	sort(p+1,p+1+n,cmp);
    	CDQ(1,n);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    贪心法之最优装载问题
    判断回文
    P1217 [USACO1.5]回文质数 Prime Palindromes
    李白打酒
    P1036 选数
    P1028 数的计算
    P1316 丢瓶盖
    P1181 数列分段Section I
    P1182 数列分段`Section II`
    P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15139811.html
Copyright © 2011-2022 走看看