Bzoj4237 cdq分治+树状数组+单调栈
二维平面在某区域内点的问题,要么树套树,kdtree,要么就是cdq分治了。
然而这题树套树和kdtree都不是很好搞的样子,于是我们就只能cdq分治了。
首先把点按照横坐标x排序,在每一层我们需要算出右边的点和左边的点组成的点对的贡献。
我们先把这些点按照纵坐标降序排列。
考虑我们按照纵坐标从大到小扫描到的每一个点。
如果他是右边的点,需要横坐标比他上面的点大才能直接加入,否则他会挡住其右上方的点,使其无法成为答案。
于是单调栈维护一下就好了。
对于左边的点,他能构成答案的纵坐标区间,一定要在他本身纵坐标以上且其右上方的点的最低纵坐标以下才行。
所以这个,我们可以用树状数组以横坐标x为下标维护纵坐标y的后缀min(什么你说树状数组只能维护前缀?后缀坐标转化为n-x[i]+1不就成前缀了?)。
然后就是查询,由于我懒得考虑二分的细节了,所以又用另外一个树状数组维护右面的点在纵坐标y上的区间和。
详见下面的图。
注意这题保证横纵坐标没有重复,所以对拍写maker的时候注意不要出重复坐标,否则网上的代码谁跟谁跑的都不一样,别问我怎么知道的。
然后给一组数据:
5
3 1
1 3
2 5
4 2
5 4
答案是4。
最后上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lli long long int
using namespace std;
const int maxn=2e5+1e2;
const int inf=0x3f3f3f3f; struct Node {
int x,y;
friend bool operator < (const Node &a,const Node &b) {
return a.x < b.x;
}
}ns[maxn]; int x[maxn],y[maxn];
int id[maxn],stk[maxn],top;
int n;
lli ans; struct BinaryIndexTreeA {
int dat[maxn];
#define lowbit(x) (x&-x)
BinaryIndexTreeA() { memset(dat,0x3f,sizeof(dat)); }
inline void update(int pos,int x) {
while( pos <= n ) dat[pos] = min( dat[pos] , x ) , pos += lowbit(pos);
}
inline int query(int pos) {
int ret = inf;
while( pos ) ret = min( ret , dat[pos] ) , pos -= lowbit(pos);
return ret;
}
inline void reset(int pos) {
while( pos <= n ) dat[pos] = inf , pos += lowbit(pos);
}
}bx;
struct BinaryIndexTreeB {
lli dat[maxn];
#define lowbit(x) (x&-x)
inline void update(int pos,int x) {
while( pos <= n ) dat[pos] += x , pos += lowbit(pos);
}
inline lli query(int pos) {
lli ret = ;
while( pos ) ret += dat[pos], pos -= lowbit(pos);
return ret;
}
inline void reset(int pos) {
while( pos <= n ) dat[pos] = , pos += lowbit(pos);
}
}by; inline bool cmp(int a,int b) {
return y[a] < y[b];
}
inline void solve(int l,int r) {
if( l == r ) return;
const int mid = ( l + r ) >> ;
for(int i=l;i<=r;i++) id[i] = i;
sort(id+l,id+r+,cmp);
top = ;
for(int i=r;i>=l;i--) {
const int p = id[i];
if( p > mid ) {
while( top && x[stk[top]] > x[p] ) by.update(y[stk[top--]],-);
stk[++top] = p;
by.update(y[p],);
} else {
int mxy = bx.query(n-x[p]+);
mxy = min( mxy , n );
ans += by.query(mxy) - by.query(y[p]-);
bx.update(n-x[p]+,y[p]);
}
}
for(int i=r;i>=l;i--) {
const int p = id[i];
if( p > mid ) by.reset(y[p]);
else bx.reset(n-x[p]+);
}
solve(l,mid);
solve(mid+,r);
} inline void refac(int* sou) {
static int srt[maxn],len;
memcpy(srt+,sou+,sizeof(int)*n);
sort(srt+,srt++n);
len = unique(srt+,srt++n) - srt - ;
for(int i=;i<=n;i++) sou[i] = lower_bound(srt+,srt++len,sou[i]) - srt;
}
inline void ncpy(int ope) {
if( ope == ) {
for(int i=;i<=n;i++)
ns[i].x = x[i] , ns[i].y = y[i];
} else if( !~ope ) {
for(int i=;i<=n;i++)
x[i] = ns[i].x , y[i] = ns[i].y;
}
} int main() {
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",x+i,y+i); refac(x) , refac(y);
ncpy() , sort(ns+,ns++n) , ncpy(-);
solve(,n); printf("%lld\n",ans); return ;
}
Bzoj4237 cdq分治+树状数组+单调栈的更多相关文章
- BZOJ4237 稻草人(分治+树状数组+单调栈)
如果要询问的某个纵坐标为inf的点左边是否有点能与其构成所要求的矩形,只要用个单调栈就可以了.可以想到用分治来制造单调性. 按横坐标排序,每次考虑跨过分治中心的矩形.考虑右边的每个点能与左边的哪些点构 ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
- 【bzoj2225】[Spoj 2371]Another Longest Increasing CDQ分治+树状数组
题目描述 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. 样例输入 8 1 3 3 2 1 1 4 5 ...
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
- LOJ3146 APIO2019路灯(cdq分治+树状数组)
每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
考虑答案的构成,发现是一个有限制条件的偏序问题. 然后三个维度的DP,可以排序.CDQ.树状数组各解决一维. #include <map> #include <cmath> # ...
- HDU 4247 Pinball Game 3D(cdq 分治+树状数组+动态规划)
Pinball Game 3D Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- Spring整合Quartz定时任务 在集群、分布式系统中的应用(Mysql数据库环境)
Spring整合Quartz定时任务 在集群.分布式系统中的应用(Mysql数据库环境) 转载:http://www.cnblogs.com/jiafuwei/p/6145280.html 单个Q ...
- CF #442 div2
A 判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人.. /** @Date : 2017-10-24 16:04:41 * @FileName: A.cpp * @P ...
- JMS学习(三)ActiveMQ Message Persistence
1,JMS规范支持两种类型的消息传递:persistent and non-persistent.ActiveMQ在支持这两种类型的传递方式时,还支持消息的恢复.中间状态的消息(message are ...
- 用原生js对表格排序
阿里的模拟笔试题,当时时间有限没写出来,其实是因为自己对原生dom操作不熟悉,这里补一下. 题目的大意是有一个表格,如代码所示 <table> <tr> <th>N ...
- 关于如何在Python中使用静态、类或抽象方法的权威指南
Python中方法的工作方式 方法是存储在类属性中的函数,你可以用下面这种方式声明和访问一个函数 >>> class Pizza(object): ... def __init__( ...
- F. Ivan and Burgers(线性基,离线)
题目链接:http://codeforces.com/contest/1100/problem/F 题目大意:首先输入n,代表当前有n个数,然后再输入m,代表m次询问,每一次询问是询问区间[l,r], ...
- Bug Bounty Reference
https://github.com/ngalongc/bug-bounty-reference/blob/master/README.md#remote-code-execution Bug Bou ...
- MySQL灾备恢复在线主从复制变成主主复制及多源复制【转】
生产主主复制(A<--->B),和灾备主从复制(B--->C).当生产出现问题时,数据写入切换到灾备数据库,待生产恢复后,将灾备回写到生产.步骤如下: 1.灾备与生产其中一台建立主主 ...
- mysql5.7.20:安装教程
从mysql官网下载安装包:/mysql-5.7.20-linuxglibc2.12-x86_64.tar.gz #切换目录 cd /usr/local #解压下载的安装包 tar -zxvf /so ...
- hashlib和hmac
hashlib hashlib模块用于加密相关的操作,代替了md5和sha模块,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法. #!/usr/bin/env p ...