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) ...
随机推荐
- bzoj千题计划226:bzoj2763: [JLOI2011]飞行路线
http://www.lydsy.com/JudgeOnline/problem.php?id=2763 这也算分层图最短路? dp[i][j]到城市i,还剩k次免费次数的最短路 #include&l ...
- Spring RedisTemplate操作-HyperLogLog操作(7)
@Autowired @Resource(name="redisTemplate") private RedisTemplate<String, String> rt; ...
- [转载]10款流行的Markdown编辑器
10款流行的Markdown编辑器 http://www.csdn.net/article/2014-05-05/2819623 作为一个开源人,如果你不会使用Markdown语法,那你就OUT了!M ...
- SpringSecurity csrf验证忽略某些请求
前几天项目中遇到springSecurity问题,研究了大半天,掉进了csrf的坑,先认识一下csrf CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟 ...
- shape-outside 矩形之外的另一种思路
http://docs.webplatform.org/wiki/css/properties/shape-outside
- PHP复制文件夹及文件夹内的文件
//1.取被复制的文件夹的名字://2.写出新的文件夹的名字://3.调用此函数,将旧.新文件夹名字作为参数传递://4.如需复制文件夹内的文件,第三个参数传1,否则传0: public functi ...
- google浏览器测试时清理缓存、强制不用缓存刷新快捷键(常用、效率)
Ctrl+Shift+Del 清除Google浏览器缓存的快捷键 Ctrl+Shift+R 重新加载当前网页而不使用缓存内容
- (FFT)A+B Problem
题目链接:https://cn.vjudge.net/contest/280041#problem/B 题目大意:给你n个数,然后让你找满足a[i] + a[j] = a[k] 的情况总数. 具体思路 ...
- HDU 6395 Sequence 杜教板子题
题目意思非常明确,就是叫你求第n项,据我们学校一个大佬说他推出了矩阵,但是我是菜鸡,那么肯定是用简单的方法水过啦!我们先p^(1/2)的复杂度处理出i=[i,p]范围内的所有种类的(int)(p/i) ...
- nginx + php + centos 6.3
2014年2月7日 22:34:52 PHP 5.5.9 http://cn2.php.net/distributions/php-5.5.9.tar.bz2 nginx 1.5.10 http:// ...