稻草人

Time Limit: 40 Sec  Memory Limit: 256 MB
[Submit][Status][Discuss]

Description

  JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典。
  有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地。和启示中的一样,田地需要满足以下条件:
  田地的形状是边平行于坐标轴的长方形;
  左下角和右上角各有一个稻草人;
  田地的内部(不包括边界)没有稻草人。
  给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数

Input

  第一行一个正整数N,代表稻草人的个数
  接下来N行,第i行(1<=i<=N)包含2个由空格分隔的整数Xi和Yi,表示第i个稻草人的坐标

Output

  输出一行一个正整数,代表遵从启示的田地的个数

Sample Input

  4
  0 0
  2 2
  3 4
  4 3

Sample Output

  3

HINT

  1<=N<=2*10^5
  0<=Xi<=10^9(1<=i<=N), Xi(1<=i<=N)互不相同。
  0<=Yi<=10^9(1<=i<=N), Yi(1<=i<=N)互不相同。

Solution

  O(n^2)做法很显然,既然这样,我们就使用惯用套路,我们先对 y 进行分治,将上面的点视为右上角的点下面的视为左下角的点,统计答案。
  首先把两部分的点分别按照 x 升序排序
  然后枚举上面的每个点
  显然,约束到它拓展的是 在它左下方最接近的点
  同时,下面的点最近的右上方点约束到点的拓展。

  那我们对于上面维护一个 y 递增的单调栈,对下面维护一个 y 递减单调栈
  枚举到上面的点的时候,把 x 小于它的下面的点加入下面的那个单调栈,然后二分一下可行的位置就可以了。
  (显然,只有当下面的x > 上面单调栈倒数第二个点的 x 的时候 才可以被加入答案)

  (middle写成了mid调了一个小时!好气呀(╯‵□′)╯︵┻━┻)

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long s64; const int ONE = ; int get()
{
int res = , Q = ; char c;
while( (c = getchar()) < || c > )
if(c == '-') Q = -;
if(Q) res = c - ;
while( (c = getchar()) >= && c <= )
res = res * + c - ;
return res * Q;
} int n; struct point
{
int x, y;
}a[ONE]; bool cmpx(const point &a, const point &b) {return a.x < b.x;}
bool cmpy(const point &a, const point &b) {return a.y < b.y;} int Stk_down[ONE], Stk_up[ONE];
s64 Ans; void Solve(int l, int r)
{
if(l >= r) return;
int mid = l + r >> ; sort(a + l, a + r + , cmpy);
sort(a + l, a + mid + , cmpx);
sort(a + mid + , a + r + , cmpx); int top_up = , top_down = ;
int now = l; for(int i = mid + ; i <= r; i++)
{
while(top_up > && a[Stk_up[top_up]].y >= a[i].y) top_up--;
Stk_up[++top_up] = i; while(now <= mid && a[now].x <= a[i].x)
{
while(top_down > && a[Stk_down[top_down]].y <= a[now].y) top_down--;
Stk_down[++top_down] = now;
now++;
} int left = , right = top_down, pos = ;
int lx = top_up - > ? a[Stk_up[top_up - ]].x : -; while(left < right - )
{
int middle = left + right >> ;
if(a[Stk_down[middle]].x >= lx)
right = middle;
else
left = middle;
} if(a[Stk_down[left]].x >= lx) pos = left;
else
if(a[Stk_down[right]].x >= lx) pos = right; if(pos) Ans += top_down - pos + ;
} Solve(l, mid), Solve(mid + , r);
} int main()
{
n = get();
for(int i = ; i <= n; i++)
a[i].x = get(), a[i].y = get(); Solve(, n);
printf("%lld", Ans);
}

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

  1. BZOJ4237 稻草人 分治 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/8682572.html 题目传送门 - BZOJ4237 题意 平面上有$n(n\leq 2\times 10^ ...

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

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

  3. 【BZOJ4237】 稻草人 CDQ分治+单调栈

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

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

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

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

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

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

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

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

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

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

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

  9. bzoj4237 稻草人——分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4237 分治: 先把所有点按 y 排序,然后二分递归: 对于每个 mid ,计算经过它的矩形的 ...

随机推荐

  1. bond下改变网卡

    浪潮服务器打开控制台 用ip addr查看哪个网卡是绑定的,eth2和eth4是绑定状态 用mv命令,更改网卡名称 并将每个网卡里的信息更改 reboot,重启 ip addr查看,eth6和eth8 ...

  2. 【Leetcode】771. Jewels and Stones

    (找了leetcode上最简单的一个题来找一下存在感) You're given strings J representing the types of stones that are jewels, ...

  3. excel表中判断A列与B列内容是否相同,相同的话在C列按条件输出!

    判断两列数据是否相同,有以下几个函数判断(做笔记于此,方便以后查找): 1.=IF(AND(A4=B4),"相同","") 在C列输出相同字符 2.=IF(A1 ...

  4. BZOJ 1483 梦幻布丁(链表+启发式合并)

    给出一个长度为n的序列.支持两种操作: 1.把全部值为x的修改成y.2.询问序列有多少连续段. 我们可以对于每个值建立一个链表.对于操作1,则可以将两个链表合并. 对于操作2,只需要在每次合并链表的时 ...

  5. 【bzoj4244】邮戳拉力赛 背包dp

    题目描述 IOI铁路是由N+2个站点构成的直线线路.这条线路的车站从某一端的车站开始顺次标号为0...N+1. 这条路线上行驶的电车分为上行电车和下行电车两种,上行电车沿编号增大方向行驶,下行电车沿编 ...

  6. 转发---[沧海拾遗]java并发之CountDownLatch、Semaphore和CyclicBarrier

    JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch CountDownLatch是一个计 ...

  7. BZOJ3811 玛里苟斯(线性基+概率期望)

    k=1的话非常好做,每个有1的位都有一半可能性提供贡献.由组合数的一些性质非常容易证明. k=2的话,平方的式子展开可以发现要计算的是每一对位提供的贡献,于是需要计算每一对位被同时选中的概率.找出所有 ...

  8. InnoDB事务日志(redo log 和 undo log)详解

    数据库通常借助日志来实现事务,常见的有undo log.redo log,undo/redo log都能保证事务特性,undolog实现事务原子性,redolog实现事务的持久性. 为了最大程度避免数 ...

  9. Zookeeper(一) zookeeper基础使用

    一.Zookeeper是什么 (安装的是3.4.7) ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现.它提供了简单原始的功能, ...

  10. Hive(六)hive执行过程实例分析与hive优化策略

    一.Hive 执行过程实例分析 1.join 对于 join 操作:SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.useri ...