题意 给出n个二维点(2e5) 和 q个询问(1e4) 每个询问给lr 问点l到r间有多少对点的曼哈顿距离<=d 点的坐标<=108

想出了莫队算法 复杂度n^1.5 看起来很科学 但是每次del和add点是直接进行暴力扫当前LR区间的点来算 ans将要增加/减少多少 实际这样的复杂度是V^2.5 会t掉

由于是在二维上找一定范围的点的数目 就可以想到KDTree V^1.5log(n)在15s下还是很科学的

做了一些曼哈顿距离的getdis函数 调完又t了。。

我使用了一下青岛的K的写法 开出三个维度 x y id 每次询问的是 和x1y1曼哈顿距离<=d 并且 L <= id <= R 的点 因为曼哈顿不是一个矩形 是一个正方形旋转了的图形 搜起来会比较麻烦

但是我感觉这个就是正解。。在网上也百度不到题解 于是出去问了一下别人对这个题的看法 然而也是莫队+KDT做的 就很迷茫

要来代码一看 有一个和我不同的是这样的 把输入进去的xy 都变成x+y 和 x-y 在查询的时候不围绕改变后的xy做一个曼哈顿的查询 而是直接查询矩形

xl = x - d   xr = x + d   yl = y - d   yr = y + d  这样

查了查对这个优化的意义 这个优化的意思 是 把曼哈顿距离转化为切比雪夫距离

http://m.blog.csdn.net/article/details?id=47259831 这个里面讲的

旋转之前两个点的曼哈顿距离是d 那么旋转后两个点的切比雪夫距离也是d 所以由一个点就可以求出来一个矩阵出来 KDT跑矩阵很快

还有一个点 就是KDT的删除点

KDT的插入点是很简单的logn操作 但是删除点的话 由于这个点可能管辖一定的点 删除了它就需要从它的孩子中找出一个点来管辖这个区域 相当于每次删除都重构

其实不需要这样 我们可以先把这棵树建出来 一开始这个树只有形状 但是点都没有放进去 每次放进去一个点就相当于点亮一个点

可以做一个类似于离线的操作 我们现在已经知道哪些点会被插入进这个树了 只要它进去 我们就记录下来

然后用这些点的形状建树 虽然一开始没有点被插进去

我们在结构体里面定义val代表当前的管辖点存在与否/有多少个 sum代表这个区域有多少个 fa代表这个点的父亲节点是谁

所以每次删除或者插入一个点 只需要改掉这个点的val 然后把这个点及其先辈的sum改了就可以了 由于我们事先知道了所有的点 所以建出来的树深度还是logn的

这种KDT写法也是很优雅的。。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define pb push_back int n , d , q ;
int m , root , cmp_d ;
int xl , xr , yl , yr ;
int L , R ; struct node {
int d[3] , Max[3] , Min[3] ;
int sum ;
int fa ;
int val ;
int l , r ;
int id ;
}tr[200050];
bool cmp(node a , node b) {
return a.d[cmp_d] < b.d[cmp_d] ;
}
int ix[200050] , iy[200050] ; int pos[200050] ;
struct no {
int l , r ;
int id ;
}xw[10050];
bool cmp2(no a , no b) {
if(pos[a.l] == pos[b.l]) return a.r < b.r ;
return a.l < b.l ;
}
int an ;
int ans[10050] ;
void up(int p , int k) {
for(int i=0;i<2;i++) {
if(tr[p].Max[i] < tr[k].Max[i]) tr[p].Max[i] = tr[k].Max[i] ;
if(tr[p].Min[i] > tr[k].Min[i]) tr[p].Min[i] = tr[k].Min[i] ;
}
tr[p].sum += tr[k].sum ;
}
int w[200050] ;
int build(int l , int r , int D , int fa) {
int mid = (l + r) >> 1 ;
cmp_d = D ;
nth_element(tr+l+1,tr+mid+1,tr+r+1,cmp) ;
w[tr[mid].id] = mid ;
tr[mid].fa = fa ;
tr[mid].val = 0 ;
tr[mid].sum = 0 ;
for(int i = 0 ; i < 2 ; i ++ ) tr[mid].Max[i] = tr[mid].Min[i] = tr[mid].d[i] ;
if(l != mid) tr[mid].l = build(l , mid-1 , D^1 , mid) ; else tr[mid].l = 0 ;
if(r != mid) tr[mid].r = build(mid+1 , r , D^1 , mid) ; else tr[mid].r = 0 ;
if(tr[mid].l) up(mid , tr[mid].l) ;
if(tr[mid].r) up(mid , tr[mid].r) ;
return mid ;
}
void upda(int rt , int val) {
tr[rt].val += val ;
while(rt) {
tr[rt].sum += val ;
rt = tr[rt].fa ;
}
}
int query(int p) {
if(tr[p].sum == 0) return 0 ;
if(tr[p].Max[0] < xl || tr[p].Min[0] > xr || tr[p].Max[1] < yl || tr[p].Min[1] > yr) return 0 ;
if(tr[p].Max[0] <= xr && tr[p].Min[0] >= xl && tr[p].Max[1] <= yr && tr[p].Min[1] >= yl) return tr[p].sum ;
int ret = 0 ;
if(tr[p].d[0] <= xr && tr[p].d[0] >= xl && tr[p].d[1] <= yr && tr[p].d[1] >= yl) ret += tr[p].val ;
if(tr[p].l) ret += query(tr[p].l) ;
if(tr[p].r) ret += query(tr[p].r) ;
return ret ;
}
void cxh(int x , int y) {
xl = x - d ; xr = x + d ;
yl = y - d ; yr = y + d ;
} int main () {
int cas = 1 ;
while(scanf("%d%d%d" , &n , &d , &q) != EOF) {
int sz = sqrt(n) ;
for(int i = 1 ; i <= n ; i ++ ) {
scanf("%d%d" , &ix[i] , &iy[i]) ;
pos[i] = i / sz ;
tr[i].l = tr[i].r = 0 ;
tr[i].d[0] = ix[i] + iy[i] ;
tr[i].d[1] = ix[i] - iy[i] ; int z = ix[i] ;
ix[i] = ix[i] + iy[i] ;
iy[i] = z - iy[i] ; tr[i].id = i ;
}
root = build(1 , n , 0 , 0) ;
an = 0 ;
for(int i = 1 ; i <= q ; i ++ ) {
scanf("%d%d" , &xw[i].l , &xw[i].r) ;
xw[i].id = i ;
}
L = 0 ;
R = 0 ;
sort(xw+1,xw+1+q,cmp2) ;
for(int i = 1 ; i <= q ; i ++ ) {
while(L < xw[i].l) {
cxh(ix[L] , iy[L]) ;
upda(w[L] , -1) ;
L ++ ;
an -= query(root) ;
}
while(L > xw[i].l) {
L -- ;
cxh(ix[L] , iy[L]) ;
an += query(root) ;
upda(w[L] , 1) ;
}
while(R < xw[i].r) {
R ++ ;
cxh(ix[R] , iy[R]) ;
an += query(root) ;
upda(w[R] , 1) ;
}
while(R > xw[i].r) {
cxh(ix[R] , iy[R]) ;
upda(w[R] , -1) ;
R -- ;
an -= query(root) ;
}
ans[xw[i].id] = an ;
}
printf("Case %d:\n" , cas ++ ) ;
for(int i = 1 ; i <= q ; i ++ ) printf("%d\n" , ans[i]) ;
}
}

CSU 1786 莫队+KDTree的更多相关文章

  1. CSU 1515 Sequence (莫队算法)

    题意:给n个数,m个询问.每个询问是一个区间,求区间内差的绝对值为1的数对数. 题解:先离散化,然后莫队算法.莫队是离线算法,先按按询问左端点排序,在按右端点排序. ps:第一次写莫队,表示挺简单的, ...

  2. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

  3. NBUT 1457 莫队算法 离散化

    Sona Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format: Submit Status Practice NBUT 145 ...

  4. 【填坑向】bzoj2038小Z的袜子 莫队

    学莫队必做题,,,但是懒得写.今天来填个坑 莫队水题 莫队实际上就是按一个玄学顺序来离线计算询问,保证复杂度只会多一个n1/2,感觉是玄学(离线算法都很玄学) 易错点:要开long long(卡我半天 ...

  5. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  6. NPY and girls-HDU5145莫队算法

    Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...

  7. Codeforces617 E . XOR and Favorite Number(莫队算法)

    XOR and Favorite Number time limit per test: 4 seconds memory limit per test: 256 megabytes input: s ...

  8. Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...

  9. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

随机推荐

  1. bsd socket 网络通讯必备工具类

    传输数据的时候都要带上包头,包头有简单的又复杂的,简单的只要能指明数据的长度就够了. 这里我写了一个工具类,可以方便地将整型的数据长度转换为长度为 4 的字节数组. 另一方面,可以方便的将长度为 4 ...

  2. C#访问修饰符比较

  3. Sql注入基础_access注入

    1.access注入攻击片段-联合查询 2.access注入攻击片段-逐字猜解法 3.Access偏移注入(表名和列名猜解成功率不是百分百,猜解不到) access注入攻击片段-联合查询法 判断注入 ...

  4. TFS二次开发-基线文件管理器(5)-源码文件的读取

      在上一节中,我们在保存标签之前,已经将勾选的文件路径保存到了Listbox中,这里只需要将保存的数据输出去为txt文档就可以做版本控制了.   版本文件比较复杂的是如何读取,也就是如何通过文件路径 ...

  5. unity 人物描边锯齿

    项目原来实现描边用了2个pass,一个pass cull back 渲染政策,一个cull front 渲染轮廓,但问题是锯齿特别明显 尝试了下边缘光实现描边,效果更不行,边线是断的

  6. python多进程编程(二)

    进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进 ...

  7. 前端基础-html(1)

    写在前面: 前端               后端 C(client)        S(server) B(browser)      S(server) 以用户为出发点 一.web标准 1)web ...

  8. java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist

    权限问题,授权给 root 所有sql 权限 在Navicat for MySQL中按F6进入命令列界面 mysql> grant all privileges on *.* to root@& ...

  9. NodeJS的一些总结

    NodeJS的一些总结 Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”. 当前的服务器程序有什么问题?我们来做个数学题. 在 Java™ 和 PHP 这类语言中,每个连接都 ...

  10. 【转载】Java中使用Jedis操作Redis

    1 package com.test; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.Li ...