• ●BZOJ 4237 稻草人


    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4237

    题解:

    CDQ分治,单调栈

    把所有点先按x从小到大排序,然后去CDQ分治y坐标。
    在分治的每一层,把所有的点平均地分为上下两个部分,
    然后计算下面的点可以对上面的每个点分别造成多少的贡献:
    (也就是说,对于上面的每个点,以它作为右上角,看下面的点中有多少个合法的左下角)
    假设现在枚举到了上面的第k个点,
    如果下面存在这样两个点i,j满足Xi<Xj且Yi<Yj,那么必然i点无法作为一个合法的左下角。
    所以我们对下面的X坐标小于Xk的点维护一个Y单调下降的栈,
    那么现在是不是栈的大小就是对k点而言,下面合法的左下角的点数。
    答案是否定的,因为k点同样会受到上面的点对它的影响,
    考虑在上面部分存在这么一个点w,满足Xw<Xk且Yw<Yk,
    那么必然在下面部分的合法的左下角的x坐标要大于Xw。
    所以具体做法就是,对上面的点维护一个单调上升的栈,对下面的点维护一个单调下降的栈,
    然后对于每个上面的点,在下面的点维护出来的单减栈中去二分出合法的左下角的个数,然后累加进答案。
    复杂度$O(Nlog^2N)$


    代码:

    #include<bits/stdc++.h>
    #define MAXN 200005
    using namespace std;
    long long ANS;
    int N,intop,detop;
    int A[MAXN],instk[MAXN],destk[MAXN];
    struct Point{
    	int x,y;
    	bool operator <(const Point &rtm) const{
    		return x<rtm.x;
    	}
    }P[MAXN];
    int binary(int l,int r,int v){
    	static int mid,ret; ret=r+1;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(destk[mid]>v) ret=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return ret;
    }
    void CDQ(int l,int r){
    	static int tmpl[MAXN],tmpr[MAXN];
    	if(l==r) return;
    	int mid=(l+r)>>1,bl=l-1,br=mid,p;
    	intop=detop=0;
    	for(int i=l;i<=r;i++){
    		if(A[i]>mid){
    			while(intop&&A[instk[intop]]>A[i]) intop--;
    			instk[++intop]=i; tmpr[++br]=A[i];
    			p=binary(1,detop,instk[intop-1]); ANS+=detop-p+1; 
    		}
    		else{
    			while(detop&&A[destk[detop]]<A[i]) detop--;
    			destk[++detop]=i; tmpl[++bl]=A[i];
    		}
    	}
    	for(int i=l;i<=mid;i++) A[i]=tmpl[i];
    	for(int i=mid+1;i<=r;i++) A[i]=tmpr[i];
    	CDQ(l,mid); CDQ(mid+1,r);
    }
    int main(){
    	static int tmpy[MAXN];
    	scanf("%d",&N);
    	for(int i=1;i<=N;i++){
    		scanf("%d%d",&P[i].x,&P[i].y);
    		tmpy[i]=P[i].y;
    	}
    	sort(P+1,P+N+1); sort(tmpy+1,tmpy+N+1);
    	for(int i=1;i<=N;i++) A[i]=lower_bound(tmpy+1,tmpy+N+1,P[i].y)-tmpy;
    	CDQ(1,N);
    	printf("%lld
    ",ANS);
    	return 0;
    }
    

      

  • 相关阅读:
    Android内存分析和调优(中)
    Android内存分析和调优(上)
    背包九讲之四:混合背包问题:01,完全,多重的混合
    背包九讲之三:多重背包问题:一个物品允许选有限次
    背包九讲之二:完全背包问题:一个物品允许选多次
    背包九讲之一:01背包问题:一个物品只允许选一次
    动态规划:最长递增子序列
    动态规划:采油区域
    Hankson的趣味题
    动态规划:传纸条
  • 原文地址:https://www.cnblogs.com/zj75211/p/8552013.html
Copyright © 2020-2023  润新知