题目传送门

  传送点I

  传送点II

题目大意

  平面上有$n$个点。问存在多少个矩形使得只有左下角和右上角有点。

  考虑枚举左下角这个点。然后看一下是个什么情况:

  嗯对,是个单调栈。但不可能暴力去求每个点右侧和上方的点的单调栈。

  注意到如果给单调栈设个上界,那么顶多会削掉一些点,不会发生大的改变。

  考虑CDQ分治,然后按照$y$从大到小排序。枚举左边的点然后不断把右边纵坐标大于它的点加入单调栈。(把横坐标比它大的全弹掉)

  然后还需要考虑一个问题:

  

  绿色点上方的点不能选。

  如何找到这个上界?对左边开一个单调栈。然后在单调栈上二分。然后在右边的单调栈上二分可以找到有多少点不能选。

  (今天考这道题,怀疑自己是zz,左边写一个线段树找上界,右边二分了两次)

Code

 /**
* bzoj
* Problem#4237
* Accepted
* Time: 7540ms
* Memory: 8332k
*/
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define ll long long
const signed int inf = (signed) (~0u >> ); typedef class IO {
public:
int sta; }IO; int __tp = ;
char __buf[]; #define digit(_x) ((_x) >= '0' && (_x) <= '9')
#define pick(_x) ((_x) = getchar()) IO& operator >> (IO& io, int& u) {
char x;
while (~(x = getchar()) && !digit(x));
for (u = x - ''; x = getchar(), digit(x); u = u * + x - '');
return io;
} IO in; template<typename T>
void alloc(T*& p, int siz) {
p = new T[(siz + )];
} typedef class Point {
public:
int x, y; boolean operator < (Point b) const {
if (y ^ b.y) return y > b.y;
return x < b.x;
}
}Point; int n;
ll res = ;
int *buf;
Point *ps, *bp;
Point *pt, *vt; inline void init() {
in >> n;
alloc(vt, n);
alloc(ps, n), alloc(bp, n);
alloc(buf, n), alloc(pt, n);
for (int i = ; i <= n; i++)
in >> ps[i].x >> ps[i].y;
} inline void discrete() {
for (int i = ; i <= n; i++)
buf[i] = ps[i].x;
sort(buf + , buf + n + );
for (int i = ; i <= n; i++)
ps[i].x = lower_bound(buf + , buf + n + , ps[i].x) - buf;
for (int i = ; i <= n; i++)
buf[i] = ps[i].y;
sort(buf + , buf + n + );
for (int i = ; i <= n; i++)
ps[i].y = lower_bound(buf + , buf + n + , ps[i].y) - buf;
} int search(Point* pt, int tp, int y) {
int l = , r = tp;
while (l <= r) {
int mid = (l + r) >> ;
if (pt[mid].y <= y)
r = mid - ;
else
l = mid + ;
}
return r + ;
} void dividing(int l, int r, int ql, int qr) {
if (l == r || ql > qr)
return ;
int mid = (l + r) >> ;
int pl = l - , pr = r + ;
for (int i = ql; i <= qr; i++)
if (ps[i].x <= mid)
bp[++pl] = ps[i];
else
bp[--pr] = ps[i];
reverse(bp + pr, bp + qr + );
for (int i = ql; i <= qr; i++)
ps[i] = bp[i]; int tp = , tp1 = ;
vt[] = (Point) {inf, inf};
for (int i = l; i <= pl; i++) {
while (pr <= r && ps[pr].y > ps[i].y) {
while (tp && pt[tp].x >= ps[pr].x)
tp--;
pt[++tp] = ps[pr], pr++;
}
int l = , r = tp1;
while (l <= r) {
int mid = (l + r) >> ;
if (vt[mid].x >= ps[i].x)
l = mid + ;
else
r = mid - ;
}
res += tp - search(pt, tp, vt[l - ].y) + ;
while (tp1 && vt[tp1].x <= ps[i].x)
tp1--;
vt[++tp1] = ps[i];
} dividing(l, mid, ql, pl);
dividing(mid + , r, pl + , qr);
} inline void solve() {
sort(ps + , ps + n + );
dividing(, n, , n);
printf(Auto, res);
} int main() {
init();
discrete();
solve();
return ;
}

bzoj 4237 稻草人 - CDQ分治 - 单调栈的更多相关文章

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

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

  2. bzoj 4237: 稻草人 -- CDQ分治

    4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行 ...

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

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

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

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

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

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

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

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

  7. bzoj 4237 稻草人 CDQ

    稻草人 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1433  Solved: 626[Submit][Status][Discuss] Descr ...

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

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

  9. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

随机推荐

  1. 第一次使用theos自己遇到的坑

    这里自己遇到的一些问题,总结一下: 第一个问题建立好theos工程后make出现 xcrun: error: SDK "iphoneos" cannot be located xc ...

  2. sqli-labs(十三)(hpp)

    第二十九关 这关说的是有waf,其实只是模拟waf的场景,就是说waf处理的变量和后台程序接受的变量不一致. 考验的参数污染,具体可以参考其他文章关于HPP的解释. 先看源码吧: 输入?id=1&am ...

  3. 改装原生的dialog

    改装 dialog 定制 View rootView = LayoutInflater.from(mContext). inflate(R.layout.nfc_tag_name_dialog, nu ...

  4. 回声状态网络(ESN)基础教程

    http://jlearning.cn/2017/05/29/ESN-basic-tutorial/ 最近在看回声状态网络(Echo State Network)的内容,注意到中文搜索引擎搜不到关于有 ...

  5. spring 的核心类JdbcTemplate 方法

    2018-11-29  10:28:02

  6. 线程&进程

    扯淡的yuan 并发&并行 并发:是指系统具有处理多个任务(动作)的能力. 并行:是指系统具有 同时 处理多个任务(动作)的能力. 同步&异步 同步:当进程执行到一个IO(等待外部数据 ...

  7. uva 1632 Alibaba

    题意: 一个人要从如果干个地方拿货,每个地方的货物是有存在时间的,到了某个时间之后就会消失. 按照位置从左到右给出货物的位置以及生存时间,这个人选择一个最优的位置出发,问拿完货物的最少时间. 思路: ...

  8. .net web site 和 web application 的区别

    web application 会把所有的代码编译打包成单一的库文件(.dll). web site 不会对整个的代码进行编译,在运行时须要哪一段代码就编译哪段代码.这导致web site 上线后,如 ...

  9. Linux基础命令---调整程序优先级renice

    renice renice指令可以重新调整程序运行的优先级,可以通过进程id.用户id.组id来修改优先级.修改组的等级,影响组内所有用户的所有进程优先级:修改用户等级,影响该用户的所有进程优先级.除 ...

  10. 两眼论&矩阵变现理论结合打造赚钱大模式

    两眼论&矩阵变现理论结合打造赚钱大模式 围棋有一个基本规则,就是一块棋有两只真眼,就是活棋. 围棋没有复杂的规则,它最有趣的地方是没有太多的规则和限制,由此演变出了大千世界,所以古人云“棋如人 ...