• BZOJ4237 稻草人


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:BZOJ4237

    正解:$CDQ$分治

    解题报告:

      考虑这种两维的题目,想办法用$CDQ$分治降维然后变成序列问题。

      对$y$坐标分治,每次分成两半,我只考虑上面一半的点对下面的影响(也就是田地的左下角在下面一半,右上角在上面一半)。

      对于上下的内部分别按$x$排序,我枚举上面的点,考虑以它为右上角的矩形个数:显然这个矩形要受上半部分中离它最近的$x$、$y$都比它小的点的制约,同时下半部分的点也需要满足之间没有别的点,纵坐标已经满足条件了,只需要考虑横坐标即可。

      根据上面的条件,不难看出只需要对上半部分维护一个纵坐标单增(纵坐标大于它的无法约束)的单调栈,下半部分维护一个纵坐标单减的单调栈,每次枚举上面的点的时候,把横坐标小于它的下半部分的点全部加入下面的单调栈,在下面的单调栈二分一下就能得到答案了。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int MAXN = 200011;
    int n,stack[MAXN],top,stack2[MAXN],tail;
    LL ans;
    struct node{ int x,y; }a[MAXN];
    inline bool cmpx(node q,node qq){ return q.x<qq.x; }
    inline bool cmpy(node q,node qq){ return q.y<qq.y; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void solve(int l,int r){
    	if(l==r) return ; sort(a+l,a+r+1,cmpy); int mid=(l+r)>>1;
    	sort(a+l,a+mid+1,cmpx);//down
    	sort(a+mid+1,a+r+1,cmpx);//up
    	top=tail=0; int now=l,L,R,pos,mm,cp;
    	for(int i=mid+1;i<=r;i++) {
    		while(top>0 && a[stack[top]].y>=a[i].y) top--;
    		stack[++top]=i;
    
    		while(now<=mid && a[now].x<a[i].x) {
    			while(tail>0 && a[stack2[tail]].y<=a[now].y) tail--;
    			stack2[++tail]=now;
    			now++;
    		}
    
    		L=1; R=tail; pos=-1; cp=a[stack[top-1]].x;
    		while(L<=R) {
    			mm=(L+R)>>1;
    			if(a[stack2[mm]].x>cp) pos=mm,R=mm-1;
    			else L=mm+1;
    		}
    		if(pos!=-1) ans+=tail-pos+1;
    	}
    	solve(l,mid); solve(mid+1,r);
    }
    
    inline void work(){
    	n=getint(); for(int i=1;i<=n;i++) a[i].x=getint(),a[i].y=getint();
    	a[0].x=a[0].y=-1;
    	solve(1,n);
    	printf("%lld",ans);
    }
    
    int main()
    {
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    vue cli3使用官方方法配置sass全局变量报错ValidationError: Invalid options object. Sass Loader has been initialised using an options object that does not match the API schema.
    面试必备:HashMap、Hashtable、ConcurrentHashMap的原理与区别
    Lombok介绍、使用方法和总结
    位运算
    【ZooKeeper系列】3.ZooKeeper源码环境搭建
    【ZooKeeper系列】2.用Java实现ZooKeeper API的调用
    【ZooKeeper系列】1.ZooKeeper单机版、伪集群和集群环境搭建
    弄明白CMS和G1,就靠这一篇了
    面试官,不要再问我三次握手和四次挥手
    【面试必备】小伙伴栽在了JVM的内存分配策略。。。
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6568640.html
Copyright © 2020-2023  润新知