离线好评

Description

很久很久以前,在遥远的大陆上有一个美丽的国家。统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草。有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……” “那么本质上它是一个深度优先搜索,陛下”,园丁深深地向国王鞠了一躬。 “嗯……我听说有一种怪物叫九头蛇,它非常贪吃苹果树……” “是的,显然这是一道经典的动态规划题,早在N元4002年我们就已经发现了其中的奥秘了,陛下”。 “该死的,你究竟是什么来头?” “陛下息怒,干我们的这行经常莫名其妙地被问到和OI有关的题目,我也是为了预防万一啊!” 王者的尊严受到了伤害,这是不可容忍的。看来一般的难题是难不倒这位园丁的,国王最后打算用车轮战来消耗他的实力: “年轻人,在我的花园里的每一棵树可以用一个整数坐标来表示,一会儿,我的骑士们会来轮番询问你某一个矩阵内有多少树,如果你不能立即答对,你就准备走人吧!”说完,国王气呼呼地先走了。 这下轮到园丁傻眼了,他没有准备过这样的问题。所幸的是,作为“全国园丁保护联盟”的会长——你,可以成为他的最后一根救命稻草。

Input

第一行有两个整数n,m(0≤n≤500000,1≤m≤500000)。n代表皇家花园的树木的总数,m代表骑士们询问的次数。 文件接下来的n行,每行都有两个整数xi,yi,代表第i棵树的坐标(0≤xi,yi≤10000000)。 文件的最后m行,每行都有四个整数aj,bj,cj,dj,表示第j次询问,其中所问的矩形以(aj,bj)为左下坐标,以(cj,dj)为右上坐标。

Output

共输出m行,每行一个整数,即回答国王以(aj,bj)和(cj,dj)为界的矩形里有多少棵树。

题目分析

这就是一个经典的二维数点问题。
于是这里提供两种做法:
1.树状数组离散化
2.cdq分治
 
这里是BIT做法:
 #include<bits/stdc++.h>
const int maxn = ; struct node
{
int x,y,lb,fr;
bool operator < (node a) const
{
return x==a.x?lb<a.lb:x<a.x;
}
}f[*maxn];
int n,m,cnt,tot;
int sum[maxn],ans[maxn][];
int a[maxn],b[maxn],c[maxn],d[maxn],x[maxn],y[maxn],p[*maxn]; int lowbit(int x){return x&-x;}
void add(int x){for (; x<=cnt; x+=lowbit(x)) sum[x]++;}
int query(int x)
{
int ret = ;
for (; x; x-=lowbit(x))
ret += sum[x];
return ret;
}
int read()
{
char ch = getchar();
int num = ;
for (; !isdigit(ch); ch = getchar());
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
return num;
}
int main()
{
n = read(), m = read();
for (int i=; i<=n; i++)
x[i] = read()+, y[i] = read()+, p[++cnt] = y[i];
for (int i=; i<=m; i++)
a[i] = read()+, b[i] = read()+, c[i] = read()+, d[i] = read()+,
p[++cnt] = b[i], p[++cnt] = d[i];
std::sort(p+, p+cnt+);
cnt = std::unique(p+, p+cnt+)-p-;
for (int i=; i<=n; i++)
y[i] = std::lower_bound(p+, p+cnt+, y[i])-p,
f[++tot].x = x[i], f[tot].y = y[i];
for (int i=; i<=m; i++)
{
b[i] = std::lower_bound(p+, p+cnt+, b[i])-p;
d[i] = std::lower_bound(p+, p+cnt+, d[i])-p;
f[++tot].x = a[i]-, f[tot].y = b[i]-, f[tot].lb = ,f[tot].fr = i;
f[++tot].x = a[i]-, f[tot].y = d[i], f[tot].lb = ,f[tot].fr = i;
f[++tot].x = c[i], f[tot].y = b[i]-, f[tot].lb = ,f[tot].fr = i;
f[++tot].x = c[i], f[tot].y = d[i], f[tot].lb = ,f[tot].fr = i;
}
std::sort(f+, f++tot);
for (int i=; i<=tot; i++)
if (f[i].lb) ans[f[i].fr][f[i].lb] = query(f[i].y);
else add(f[i].y);
for (int i=; i<=m; i++)
printf("%d\n",ans[i][]+ans[i][]-ans[i][]-ans[i][]);
return ;
}

这里是cdq做法:

 #include<bits/stdc++.h>
const int maxn = ;
const int maxk = ; struct point
{
int x,y,lb,mt;
point() {}
point(int a, int b, int c, int d):x(a),y(b),lb(c),mt(d) {}
bool operator < (point a) const
{
return x==a.x?abs(mt) < abs(a.mt):x < a.x;
}
}f[maxn*],s[maxn*];
int n,m,cnt,dfn,maxy;
int sum[maxk],tim[maxk],ans[maxn]; int lowbit(int x){return x&-x;}
void add(int x)
{
for (; x <= maxy; x += lowbit(x))
{
if (tim[x] != dfn) tim[x] = dfn, sum[x] = ;
sum[x]++;
}
}
int query(int x)
{
int ret = ;
for (; x; x -= lowbit(x))
if (tim[x] == dfn)
ret += sum[x];
return ret;
}
int read()
{
char ch = getchar();
int num = ;
for (; !isdigit(ch); ch = getchar());
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
return num;
}
void cdq(int l, int r)
{
if (l >= r) return;
int mid = (l+r)>>, L = l, R = mid+, now = l;
cdq(l, mid);
cdq(mid+, r);
dfn++;
while (L <= mid && R <= r)
if (f[L] < f[R]){
if (!f[L].mt) add(f[L].y);
s[now++] = f[L++];
}else{
if (f[R].mt) ans[f[R].lb] += f[R].mt*query(f[R].y);
s[now++] = f[R++];
}
while (L <= mid) s[now++] = f[L++];
while (R <= r)
{
if (f[R].mt) ans[f[R].lb] += f[R].mt*query(f[R].y);
s[now++] = f[R++];
}
for (int i=l; i<=r; i++) f[i] = s[i];
}
int main()
{
n = read(), m = read();
for (int i=; i<=n; i++)
f[++cnt].x = read()+, f[cnt].y = read()+, maxy = std::max(maxy, f[cnt].y);
for (int i=; i<=m; i++)
{
int a = read()+, b = read()+, c = read()+, d = read()+;
f[++cnt] = point(a-, b-, i, );
f[++cnt] = point(c, d, i, );
f[++cnt] = point(a-, d, i, -);
f[++cnt] = point(c, b-, i, -);
maxy = std::max(maxy, std::max(b, d));
}
cdq(, cnt);
for (int i=; i<=m; i++)
printf("%d\n",ans[i]);
return ;
}
另有关cdq的问题详见「初涉cdq」专题
 
 
 
 
END
 

初涉二维数点问题&&bzoj1935: [Shoi2007]Tree 园丁的烦恼的更多相关文章

  1. [bzoj1935][shoi2007]Tree 园丁的烦恼(树状数组+离线)

    1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 980  Solved: 450[Submit][ ...

  2. bzoj千题计划143:bzoj1935: [Shoi2007]Tree 园丁的烦恼

    http://www.lydsy.com/JudgeOnline/problem.php?id=1935 二维偏序问题 排序x,离散化树状数组维护y #include<cstdio> #i ...

  3. BZOJ1935: [Shoi2007]Tree 园丁的烦恼

    1935: [Shoi2007]Tree 园丁的烦恼 Time Limit: 15 Sec  Memory Limit: 357 MBSubmit: 552  Solved: 220[Submit][ ...

  4. BZOJ1935: [Shoi2007]Tree 园丁的烦恼(树状数组 二维数点)

    题意 题目链接 Sol 二维数点板子题 首先把询问拆成四个矩形 然后离散化+树状数组统计就可以了 // luogu-judger-enable-o2 #include<bits/stdc++.h ...

  5. [bzoj1935][Shoi2007]Tree 园丁的烦恼 _树状数组

    Tree 园丁的烦恼 bzoj-1935 Shoi-2007 题目大意:给定平面上的$n$个点,$m$次查询矩形点个数. 注释:$1\le n,m\le 5\cdot 10^5$. 想法:静态二维数点 ...

  6. [bzoj4822][Cqoi2017]老C的任务&[bzoj1935][Shoi2007]Tree 园丁的烦恼

    来自FallDream的博客,未经允许,请勿转载,谢谢. 老 C 是个程序员.     最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统.作为经验丰富的程序员,老 C 轻松地完成 ...

  7. [BZOJ1935][SHOI2007]Tree 园丁的烦恼(离线+树状数组)

    题意 给出第一象限的n个点,有m次询问,每次询问一个矩形中的点的个数.(0<=n,m<=500000,0<=xi,yi<=10000000) 题解 一眼望去不可做. 用二位前缀 ...

  8. bzoj1935: [Shoi2007]Tree 园丁的烦恼lowbit 离散化

    链接 bzoj 最好不要去luogu,数据太水 思路 一个询问转化成四个矩阵,求起点\((0,0)到(x,y)\)的矩阵 离线处理,离散化掉y,x不用离散. 一行一行的求,每次处理完一行之后下一行的贡 ...

  9. BZOJ1935:[SHOI2007]Tree 园丁的烦恼(CDQ分治)

    Description 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草.有一天国王漫步在花园里,若有所思,他问一个园丁道: ...

随机推荐

  1. 安装Net::OpenSSH 库

    perl 离线安装 Net::OpenSSH 库 Net::OpenSSH 库 下载地址https://metacpan.org/pod/Net::OpenSSH 直接获取安装包命令 wget htt ...

  2. 如何对接payjs的个人微信扫码支付接口

    在众多个人支付接口的产品中,要寻找一个稳定可靠的产品是比较难的,所幸遇到payjs,感觉逼格较高,非常满足自己的品味.推荐大家使用.下边是我在对接payjs的过程中的一些经验和技巧,分享给大家. 一. ...

  3. PostgreSQL - update语句怎么关联多个表

    问题 对于select语句,我们可以通过join/outer join来关联多个表:但是对于update语句,是不能直接通过join/outer join来关联多表数据的,这里仅针对PostgreSQ ...

  4. 整理一下 通知传值 Block传值

    Block: 一. (1) 在需要传值的界面定义属性 // 点击collectionViewCell的回调 @property (nonatomic, copy) void(^Didcollectio ...

  5. 最长上升子序列LIS(云笔记图片版)

  6. 在 Linux 环境直接复移动硬盘上的 GRUB

    手头有一块用了 10 年的旧移动硬盘,其中安装了 Debian 系统,从低版本一直升级到现在的 9 已经用了很长时间.前不久正连着那块硬盘跑着 Debian 修改文件的时候,由于一个本可避免的意外震动 ...

  7. python入门之迭代器

    迭代器 已知,可以直接作用于for循环的数据类型有: 一类是集合数据类型,如list.tuple.dict.set.str 一类是generator,包括生成器和带yield的generator fu ...

  8. Ubuntu安装指定版本的docker

    系统环境: Ubuntu 16.0.4 安装版本: docker  17.03.2 在进现在这家公司初期,需要使用rancher部署一个k8s集群,由于rancher也是由docker启动的,加上k8 ...

  9. HDU Atlantis 线段树 表达区间 矩形面积相交

    http://acm.hdu.edu.cn/showproblem.php?pid=1542 我的做法是把x轴的表示为线段,然后更新y 不考虑什么优化的话,开始的时候,把他们表达成线段,并按y排序,然 ...

  10. awk一些简单命令

    最简单地说, AWK 是一种用于处理文本的编程语言工具.AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法. 尽管操作可能会很复杂,但命令的语法始终是: awk ' ...