Tree 园丁的烦恼 bzoj-1935 Shoi-2007

题目大意:给定平面上的$n$个点,$m$次查询矩形点个数。

注释:$1\le n,m\le 5\cdot 10^5$。


想法:静态二维数点。

$Orz Winniechen$,真tm敢写$KD-Tree$,虽然$T$了..

正常这种静态的二维数点我们都要请到树状数组。最简单的就是二维树状数组。

但是发现开不下,这样的话我们依据它可以离线这一点,我们将每个询问$(x1,y1)$到$(x2,y2)$变成$4$次查询:

$(x1-1,y1-1),(x1-1,y2),(x2,y1-1),(x2,y2)$把它们哥四个都当成点放入点集。每次都相当于查询$(1,1)$到$balabala$

每个点集中的点有$4$个参数:横纵坐标,种类和系数。

种类就是这个点到底是给定的点还是查询的点。

系数的话就是容斥前面的系数:$(x1-1,y1-1)$和$(x2,y2)$前面是$1$,$(x1-1,y2)$和$(x2,y1-1)$前面是$-1$。

然后我们将点集排序,横坐标递增为第一关键字,纵坐标递增为第二关键字。

紧接着我们顺次枚举每个点,如果这个点的种类是给定点,我们将它压到树状数组里。

是一个树状数组里,我们只开一个树状数组,记录的是小于每个横坐标的点的个数。

这样的话根据我们的关键字可知,每一个有可能更新查询的点都会被提前枚举过。

如果这个点是查询,就直接查询然后累加到对应查询的编号答案上,即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
struct Node
{
int x,y,f,id;//这里跟上述的有些不一样。
//我们用f直接可以同时记录种类和系数。如果f==0,那么就表示这个点是给定的点,反之f=1或-1代表系数,直接累计即可。
}q[N<<2];
int tree[10000010];
int mx=0;
int ans[N];
inline bool cmp(const Node &a,const Node &b)
{
return a.x!=b.x?a.x<b.x:(a.y!=b.y?a.y<b.y:a.id<b.id);
}
int a,b,c,d;
int cnt;
inline int lowbit(int x) {return x&(-x);}
void fix(int x)
{
// if(!x) x++;
// puts("fix");
for(int i=x;i<=mx+1;i+=lowbit(i))
{
// printf("aha %d\n",i);
tree[i]++;
}
}
int query(int x)
{
// puts("query");
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
{
ans+=tree[i];
}
return ans;
}
int main()
{
int n,m; cin >> n >> m ;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&q[i].x,&q[i].y);
q[i].x++,q[i].y++;
mx=max(mx,q[i].y);
}
cnt=n;
// puts("Fuck 1");
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
c++,d++;
q[++cnt].x=c; q[cnt].y=d; q[cnt].f=1; q[cnt].id=i;//这里不要把系数搞错
q[++cnt].x=c; q[cnt].y=b; q[cnt].f=-1; q[cnt].id=i;
q[++cnt].x=a; q[cnt].y=d; q[cnt].f=-1; q[cnt].id=i;
q[++cnt].x=a; q[cnt].y=b; q[cnt].f=1; q[cnt].id=i;
}
// printf("Gun %d\n",cnt);
// puts("Fuck 2");
sort(q+1,q+cnt+1,cmp);
for(int i=1;i<=cnt;i++)
{
// printf("Shit %d\n",i);
if(!q[i].id) fix(q[i].y);
else ans[q[i].id]+=query(q[i].y)*q[i].f;//这就是直接压到一个变量的好处,不用特判直接加就行了,反正如果是给定点f就是0,不会影响答案。
}
// puts("Fuck 3");
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}

小结:这个想法极其常用,很多静态可离线二维数点问题都可以用这个来解决。那些动态的就让KD-Tree上吧,反正出了那种题被卡常的不可能只有你一个人/手动滑稽

[bzoj1935][Shoi2007]Tree 园丁的烦恼 _树状数组的更多相关文章

  1. [BZOJ1935][SHOI2007]Tree 园丁的烦恼(树状数组)

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

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

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

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

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

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

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

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

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

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

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

  7. 初涉二维数点问题&&bzoj1935: [Shoi2007]Tree 园丁的烦恼

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

  8. 【树状数组】bzoj1935 [Shoi2007]Tree 园丁的烦恼

    把y坐标离散化后,按x坐标排序,把询问拆成四个点,每次询问某个点左下角的点的个数,注意处理边界和重叠的情况. #include<cstdio> #include<algorithm& ...

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

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

随机推荐

  1. js模拟复制

    现在浏览器种类也越来越多,诸如 IE.Firefox.Chrome.Safari等等,因此现在要实现一个js复制内容到剪贴板的小功能就不是一件那么容易的事了.   一.实现点击按钮,复制文本框中的的内 ...

  2. 微信小程序图片选择,预览和删除

    这里均用的是小程序原生api 废话不多说直接上栗子: <view class="addImv"> <!--这个是已经选好的图片--> <view wx ...

  3. vscode常用的快捷键

    对于编程人员来说,记住一些常用的快捷键能够提高工作效率:我认为,对于编程人员来说,掌握一些常用的快捷键是非常有必要的! Ctrl + Shift + N 打开新的编辑器窗口 Ctrl + Shift ...

  4. ASP.NET MVC5 之 AspNetUsers 表增加字段

    MVC5 执行数据库迁移时,会生成一些默认的数据表,但是在实际的工作中.若用到的时候,难免要增添一些字段. 1.AspNetUsers 增加字段 A.打开MVC中的 IdentityModels.cs ...

  5. [转]linux之磁盘配额(quota)

    转自:http://www.jb51.net/LINUXjishu/78446.html 磁盘配额(quota)比较常用的几个情况是: * 针对WWW server,例如:每个人的网页空间的容量限制 ...

  6. Google广告屏蔽插件adBlock

    今天在博客园写博客的时候发现莫名其妙的在右侧被植入了广告,询问了管理员得知存在以下几种可能: 1.电信网络供应商劫持网页,植入广告 2.ADSafe(是一款去除广告的软件,效果很不错) 但经过最终排除 ...

  7. JVM中线程状态转换图

    JVM中线程的状态转换图 线程在一定条件下,状态会发生变化.线程一共有以下几种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该 ...

  8. VC窗口类的销毁-是否需要delete

    Windows窗口如果使用new的方法添加之后,在父窗口析构的时候,有些需要delete有些却不需要delete.这个的确有点坑,由于c++的实现,对于每个自己new的对象,我都会delete删除它, ...

  9. 【MySQL】RPM包安装

    操作系统:Red Hat Enterprise Linux Server release 6.5 Mysql安装包:MySQL-5.6.35-1.linux_glibc2.5.x86_64.rpm-b ...

  10. SQl基本操作——try catch

    begin try ... end try begin catch ... end catch