【bzoj4237】稻草人 分治+单调栈+二分
题目描述
输入
输出
样例输入
4
0 0
2 2
3 4
4 3
样例输出
3
题解
自己yy出来的分治+单调栈+二分
如果直接对于每个点求以它为顶点的满足条件的矩形数目比较难求,所以考虑分治处理。
按x分治,处理完左右区间后处理左边对右边的影响。
此时左半部分的x严格小于右半部分的x,如果再按x排序则没有意义,所以按照y排序。
按照y从小到大排序后,遍历区间内所有的点。对于每个右半部分的点,在左半部分里寻找答案。
我们思考:如果在左半部分扫到了这样两个点a、b:ay>by且ax>bx,那么在按y从小到大遍历时,剩下的点的y都比这两个点大,画图可知b不可能再形成矩形,所以弹掉。
即对左半部分维护一个从栈底到栈顶x值递减的单调栈,碰到不满足条件的则弹出。
再考虑右半部分:如果扫到了这样两个点a、b:ay>by且ax<bx,那么这两个点是互不影响的,直接寻找答案即可。所以b没有意义,所以弹掉。而当ay>by且ax>bx时,b限制了a形成的矩形的范围,所以应当保留,并且在遍历到a时在左半部分中二分。
即对右半部分维护一个从栈底到栈顶x值递增的单调栈,碰到不满足条件的则弹出。
综上,我们维护两个单调栈,每次遍历到一个点,就把它压到对应的单调栈中,如果这个点是右半部分的点,就在左半部分的单调栈中二分求出比栈顶元素y值大的点的个数,并累加到答案中。注意左右部分的单调栈是不同的,因为它们的意义是不同的。
这样做的时间复杂度是$O(n\log^2n)$,亲测使用归并排序,二分的常数极小,可以使时间减到5s左右。
#include <cstdio>
#include <algorithm>
#define N 200010
using namespace std;
struct data
{
int x , y;
}a[N] , tmp[N];
int s1[N] , t1 , s2[N] , t2;
long long ans;
bool cmp(data a , data b)
{
return a.x < b.x;
}
int getnum(int t)
{
int l = 1 , r = t1 , mid , tmp = t1 + 1;
while(l <= r)
{
mid = (l + r) >> 1;
if(a[s1[mid]].y >= t) tmp = mid , r = mid - 1;
else l = mid + 1;
}
return t1 - tmp + 1;
}
void solve(int l , int r)
{
if(l >= r) return;
int mid = (l + r) >> 1 , tx = a[mid].x , i , p1 = l , p2 = mid + 1;
solve(l , mid);
solve(mid + 1 , r);
for(i = l ; i <= r ; i ++ )
{
if(p2 > r || (p1 <= mid && a[p1].y < a[p2].y)) tmp[i] = a[p1 ++ ];
else tmp[i] = a[p2 ++ ];
}
t1 = t2 = 0;
for(i = l ; i <= r ; i ++ )
{
a[i] = tmp[i];
if(a[i].x <= tx)
{
while(t1 && a[i].x > a[s1[t1]].x) t1 -- ;
s1[++t1] = i;
}
else
{
while(t2 && a[i].x < a[s2[t2]].x) t2 -- ;
s2[++t2] = i;
ans += getnum(a[s2[t2 - 1]].y);
}
}
}
int main()
{
int n , i;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].x , &a[i].y);
sort(a + 1 , a + n + 1 , cmp);
solve(1 , n);
printf("%lld\n" , ans);
return 0;
}
【bzoj4237】稻草人 分治+单调栈+二分的更多相关文章
- BZOJ4237 稻草人 分治 单调栈
原文链接https://www.cnblogs.com/zhouzhendong/p/8682572.html 题目传送门 - BZOJ4237 题意 平面上有$n(n\leq 2\times 10^ ...
- 【BZOJ4237】稻草人 cdq分治+单调栈+二分
[BZOJ4237]稻草人 Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田 ...
- 【BZOJ4237】稻草人 [分治][单调栈]
稻草人 Time Limit: 40 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description JOI村有一片荒地,上面竖着N个稻草 ...
- Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】
正题 题目链接:https://loj.ac/problem/2880 题目大意 给出平面上的\(n\)个点,然后求有多少个矩形满足 左下角和右上角各有一个点 矩形之间没有其他点 \(1\leq n\ ...
- 【BZOJ4237】 稻草人 CDQ分治+单调栈
## 题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下 ...
- BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]
1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 8748 Solved: 3835[Submi ...
- bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...
- BZOJ1012最大数 [JSOI2008] 单调栈+二分
正解:单调栈+二分查找(or,线段树? 解题报告: 拿的洛谷的链接quq 今天尝试学习了下单调栈,然后就看到有个博客安利了这个经典例题?于是就去做了,感觉还是帮助了理解趴quqqqqq 这题,首先,一 ...
- 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线
区间计数 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{ ...
随机推荐
- JS字符串处理方法
1.字符方法charAt()和charCodeAt();这两个方法都接收一个参数例:<script>var stringValue = "hello world"; s ...
- python打开文件可以有多种模式
一.python打开文件可以有多种模式,读模式.写模式.追加模式,同时读写的模式等等,这里主要介绍同时进行读写的模式r+ python通过open方法打开文件 file_handler = open( ...
- vue+element ui项目总结点(二)table合计栏目,按照起始年份--截止年份 插入数据并向后追加数据以最后一条年份+1
1.oninput 事件在用户输入时触发; <template> <div class="test_box"> <p>hell,你好</p ...
- ZOJ 3466 The Hive II (插头DP,变形)
题意:有一个n*8的蜂房(6边形的格子),其中部分是障碍格子,其他是有蜂蜜的格子,每次必须走1个圈取走其中的蜂蜜,在每个格子只走1次,且所有蜂蜜必须取走,有多少种取法? 思路: 以前涉及的只是n*m的 ...
- (二)SpringMVC之执行的过程
(DispatcherServlet在Spring当中充当一个前端控制器的角色,它的核心功能是分发请求.请求会被分发给对应处理的Java类,Spring MVC中称为Handle.) ① 用户把请 ...
- The Django Book - 第四章 模板
使用模板的最基本方式:1.根据原始模板代码字符串创建一个Template对象2. 使用字典创建一套Context变量3. 调用Template对象的render方法,传入Context变量参数 In ...
- UVA1515 Pool construction (最小割模型)
如果不允许转化'#'和'.'的话,那么可以直接在'#'和'.'之间连容量为b的边,把所有'#'和一个源点连接, 所有'.'和一个汇点连接,流量不限,那么割就是建围栏(分割'#'和'.')的花费. 问题 ...
- URAL 2047 Maths (数学)
对于一个数来说,它的除数是确定的,那么它的前驱也是确定的,而起点只能是1或2,所以只要类似筛法先预处理出每个数的除数个数 ,然后递推出每个数往前的延伸的链长,更新最大长度,记录对应数字.找到maxn以 ...
- OC 导入类 #import和@class 区别
objective-c中#import和@class的区别 在Objective-C中,可以使用#import和@class来引用别的类型, 但是你知道两者有什么区别吗? @class叫做forwar ...
- 判断一个链表是否为回文结构 【题目】 给定一个链表的头节点head,请判断该链表是否为回 文结构。 例如: 1->2->1,返回true。 1->2->2->1,返回true。 15->6->15,返回true。 1->2->3,返回false。 进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂 度达到O(1)。
方式1:借助栈 空间辅助度是O(N) 方式2: 借助栈 空间复杂度是 O(n/2).只存后半个链表 方式3: 反转后半个链表 最后再反转回来 package my_basic.class_3; im ...