题目描述


JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典。

有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地。和启示中的一样,田地需要满足以下条件:

田地的形状是边平行于坐标轴的长方形;

左下角和右上角各有一个稻草人;

田地的内部(不包括边界)没有稻草人。

给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数

简述 求\(n\)个点组成的内部不含其它点的矩形有多少

Solution

为什么要专门记录这个简单的\(CDQ\)分治+单调栈简单题呢,那是因为这道题脱离了\(CDQ\)分治的模板,转更深刻的探究\(CDQ\)分治解决的问题本质

首先这道题找矩形,就要找其左下角及右上角

我们把被处在右上角的点\(b\)与左下角的点\(a\)形成有效矩形成称为\(b\)控制\(a\)

可理解为,处在左下位置的点会对右上位置的点造成贡献,被控制

我们把点按\(y\)轴排序

按\(y\)来划分上下

上下以\(x\)来归并排序(结果就是,\([ql,mid]\)的\(y\)都比\([mid+1,qr]\)的\(y\)要小,但区间内有且仅有\(x\)有序)

如图,\([ql,mid]\)为上面,\([mid+1,qr]\)为下面

因此\(a\)来自下方,\(b\)来自上方

\(Ans_b\)=(在\(b\)左侧可以成为左下角的\(a\)-被\(b\)左边的管并且不会被\(b\)管的\(a\))

对在\(b\)左侧可以成左下角的\(a\)

现在证明:如果\(a\)是满足条件的,则在\(a\)右上侧的\(a'\)就是无效的

分两种情况

因此对\(a\)我们维护一个\(y\)值单调递减的单调栈

每次维护\(x<b_x\)的单调栈即可

for(;q[j].x<q[i].x&&j<=mid;++j){//下,保存的是所有可以成为左下角的点
while(topmax&&q[j].y>q[stmax[topmax]].y)--topmax;
stmax[++topmax]=j;
}

被\(b\)左边的管并且不会被\(b\)管的\(a\)

现在证明:在\(b\)左下侧的\(b'\)是不会影响\(b\)管辖范围的

因此对\(b\)我们维护一个\(y\)值单调递增的单调栈

每一次

\(Ans_b\)=(在\(b\)左侧可以成为左下角的\(a\)-被\(b\)左边的管并且不会被\(b\)管的\(a\))

=\(topmax-b\)的单调栈的前栈顶管辖的\(a\)个数

实现时用二分即可找到前栈顶管辖的最后一个\(a\)位置减掉即可


inline int Find(void){
re int l=1,r=topmax,mid,ans=0;
while(l<=r){
mid=(l+r)>>1;
if(q[stmax[mid]].x<q[stmin[topmin-1]].x){ans=mid;l=mid+1;}
else r=mid-1;
}
return ans;
}
inline void CDQ(re int ql,re int qr){
re int i,j,l,r,t,mid=(ql+qr)>>1;
if(ql==qr)return ;
CDQ(ql,mid);CDQ(mid+1,qr);
j=ql;topmin=topmax=0;
for(i=mid+1;i<=qr;++i){//上,保存的是所有可以影响之后右上角点的(左下角点的个数)的点
while(topmin&&q[i].y<q[stmin[topmin]].y)--topmin;
stmin[++topmin]=i;
for(;q[j].x<q[i].x&&j<=mid;++j){//下,保存的是所有可以成为左下角的点
while(topmax&&q[j].y>q[stmax[topmax]].y)--topmax;
stmax[++topmax]=j;
}
ans+=topmax-Find();
}
l=t=ql;r=mid+1;
while(l<=mid&&r<=qr){
if(q[l].x<q[r].x)tmp[t++]=q[l++];
else tmp[t++]=q[r++];
}
while(l<=mid)tmp[t++]=q[l++];
while(r<=qr)tmp[t++]=q[r++];
for(i=ql;i<=qr;++i)q[i]=tmp[i];
}

放一个示意图(一定要手推)

【BZOJ4237】 稻草人 CDQ分治+单调栈的更多相关文章

  1. bzoj4237: 稻草人 cdq分治 单调栈

    目录 题目链接 题解 代码 题目链接 bzoj4237: 稻草人 题解 暴力统计是n^2的 考虑统计一段区间对另一端的贡献 对于y值cdq分治,降调一维 对于当前两个分治区间统计上面那部分对下面那部分 ...

  2. 【BZOJ4237】稻草人 cdq分治+单调栈+二分

    [BZOJ4237]稻草人 Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田 ...

  3. bzoj 4237 稻草人 - CDQ分治 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 平面上有$n$个点.问存在多少个矩形使得只有左下角和右上角有点. 考虑枚举左下角这个点.然后看一下是个什么情况: 嗯对,是个单调栈.但不可能暴力去求每个点右 ...

  4. [BZOJ4237]稻草人:CDQ分治+单调栈

    分析 按\(y\)排序后CDQ分治,可以发现每个点可以影响的是\(x\)坐标的一段区间,可以使用扫描线+单调栈,在单调栈上二分即可解决,时间复杂度\(O(n \log^2 n)\). 通过归并排序可以 ...

  5. Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】

    正题 题目链接:https://loj.ac/problem/2880 题目大意 给出平面上的\(n\)个点,然后求有多少个矩形满足 左下角和右上角各有一个点 矩形之间没有其他点 \(1\leq n\ ...

  6. $bzoj4237$稻草人 $cdq$分治

    正解:$cdq$分治 解题报告: 传送门$QwQ$ $umm$总感觉做过这题的亚子,,,? 先把坐标离散化,然后把所有点先按$x$排序$QwQ$,然后用类似平面最近点对的方法,先分别解决$mid$两侧 ...

  7. [BZOJ4237]稻草人(CDQ分治)

    先按y排序,二分,两边递归下去,然后处理下半部分对上半部分的贡献,即左下点在下半部分,右上点在上半部分的合法矩形个数. 两个部分均按x排序,枚举右上点p,则左下点需要满足: 1.横坐标大于上半部分纵坐 ...

  8. 【bzoj4237】稻草人 分治+单调栈+二分

    题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: ...

  9. BZOJ4237 JOISC2014 稻草人 CDQ分治、单调栈

    传送门 题意:给出平面上$N$个点,求满足以下两个条件的矩形:①左下角与右上角各有一个点:②矩形内部没有点.$N \leq 2 \times 10^5$,所有数字大于等于$0$,保证坐标两两不同 最开 ...

随机推荐

  1. Google Colab——零成本玩转深度学习

    前言 最近在学深度学习HyperLPR项目时,由于一直没有比较合适的设备训练深度学习的模型,所以在网上想找到提供模型训练,经过一段时间的搜索,最终发现了一个谷歌的产品--Google Colabora ...

  2. C++构造和解析JSON

    JSON是一种轻量级的数据交互格式,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率,实际项目中经常用到,相比xml有很多优点,问问度娘,优点一箩筐. 第三方库 json解析选用j ...

  3. php 函数篇

    1.array_values($data); 注:将关联数组转化为索引数组 <?php $a=array("Name"=>"Bill"," ...

  4. 类的练习2——python编程从入门到实践

    9-7 管理员: 管理员是一种特殊的用户.编写一个名为Admin的类,并让它继承练习9-3或者9-5的User类.添加一个名为privileges的属性,用于存储一个由字符串(如"can a ...

  5. python--osi七层模型

    OSI七层模型 OSI七层参考模型 学计算机的人想必都对OSI七层参考模型不陌生,OSI七层参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系.它是一个七层的.抽象的模型 ...

  6. 配置 web 内容的访问

    在您的 system1 上的 web 服务器的 DocumentRoot 目录下,创建一个名为 private 的目录,要求如下: 1.从 http://server.group8.example.c ...

  7. golang ---JSON-ITERATOR 使用

    jsoniter ( json-iterator )是一款快且灵活的 JSON 解析器 Jsoniter 是最快的 JSON 解析器.它最多能比普通的解析器快 10 倍之多, 独特的 iterator ...

  8. 使用@Async注解创建多线程,自定义线程池

    说明 使用@Async注解创建多线程非常的方便,还可以通过配置,实现线程池.比直接使用线程池简单太多.而且在使用上跟普通方法没什么区别,加上个@Async注解即可实现异步调用. 用法 AsyncTas ...

  9. Python进阶(二)----函数参数,作用域

    Python进阶(二)----函数参数,作用域 一丶形参角度:*args,动态位置传参,**kwargs,动态关键字传参 *args: ​ 动态位置参数. 在函数定义时, * 将实参角度的位置参数聚合 ...

  10. 解决for循环中异步处理(异步变同步)

    前沿:参考ES6语法的async/await的处理机制 先上一段代码 function getMoney(){ var money=[100,200,300] for( let i=0; i<m ...