zoukankan      html  css  js  c++  java
  • 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;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    Day 20 初识面向对象
    Day 16 常用模块
    Day 15 正则表达式 re模块
    D14 模块 导入模块 开发目录规范
    Day 13 迭代器,生成器,内置函数
    Day 12 递归,二分算法,推导式,匿名函数
    Day 11 闭包函数.装饰器
    D10 函数(二) 嵌套,命名空间作用域
    D09 函数(一) 返回值,参数
    Day 07 Day08 字符编码与文件处理
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6568640.html
Copyright © 2011-2022 走看看