【BZOJ4066】简单题(KD-Tree)

题面

BZOJ

题解

如果这题不卡空间,并且不强制在线的话

显然可以用\(CDQ\)分治做

但是它又卡空间又强制在线,于是我们欢快的来用\(KD-Tree\)吧。

用\(KD-Tree\)维护每一个点,每次询问的时候

判断询问的矩形和当前矩形的交

如果全部覆盖直接加上所有的和

如果没有交则直接返回

如果有部分交则递归处理。

我用了两种方案防止\(KD-Tree\)被卡

第一种:定时重构。大概就是每插入\(10000\)次后就重构一次

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 100200
#define mid o
#define ls (t[o].ch[0])
#define rs (t[o].ch[1])
#define cmin(a,b) (a<b?a:a=b)
#define cmax(a,b) (a>b?a:a=b)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
const double alpha=0.762333;
int D;
struct Node{int d[2],v;}a[MAX];
bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
struct KD_Node
{
int mn[2],mx[2],ch[2];
Node a;
int sum;
void clear(){mn[0]=mn[1]=mx[0]=mx[1]=a.d[0]=a.d[1]=a.v=sum=0;}
}t[MAX];
int tot,Num;
void update(int x,int y)
{
cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
}
void pushup(int o)
{
t[o].mn[0]=t[o].mx[0]=t[o].a.d[0];
t[o].mn[1]=t[o].mx[1]=t[o].a.d[1];
t[o].sum=t[ls].sum+t[rs].sum+t[o].a.v;
if(ls)update(o,ls);if(rs)update(o,rs);
}
int Build(int l,int r,int nd)
{
int mid=(l+r)>>1;D=nd;
nth_element(&a[l],&a[mid],&a[r+1]);
t[o].a=a[mid];
if(l<mid)ls=Build(l,mid-1,nd^1);else ls=0;
if(r>mid)rs=Build(mid+1,r,nd^1);else rs=0;
pushup(o);return o;
}
void insert(int &o,int nd,Node a)
{
if(!o){o=tot;t[o].a=a;pushup(o);return;}
if(t[o].a.d[nd]<a.d[nd])insert(rs,nd^1,a);
else insert(ls,nd^1,a);
pushup(o);
}
int checksame(KD_Node a,int x1,int x2,int y1,int y2)
{
if(x1<=a.mn[0]&&a.mx[0]<=x2&&y1<=a.mn[1]&&a.mx[1]<=y2)return 1;//all
if(x2<a.mn[0]||a.mx[0]<x1)return 0;
if(y2<a.mn[1]||a.mx[1]<y1)return 0;
return 2;
}
int Query(int o,int x1,int x2,int y1,int y2)
{
int ret=0;
if(t[o].a.d[0]>=x1&&t[o].a.d[0]<=x2&&t[o].a.d[1]>=y1&&t[o].a.d[1]<=y2)
ret+=t[o].a.v;
if(ls)
{
int d=checksame(t[ls],x1,x2,y1,y2);
if(d==1)ret+=t[ls].sum;
if(d==2)ret+=Query(ls,x1,x2,y1,y2);
}
if(rs)
{
int d=checksame(t[rs],x1,x2,y1,y2);
if(d==1)ret+=t[rs].sum;
if(d==2)ret+=Query(rs,x1,x2,y1,y2);
}
return ret;
}
int N,rt;
int main()
{
N=read();
int lans=0,opt,x,y,A,x1,y1,x2,y2;
while(233)
{
opt=read();
if(opt==3)break;
if(opt==1)
{
x=read()^lans,y=read()^lans,A=read()^lans;
insert(rt,0,a[++tot]=(Node){x,y,A});
if(tot%10000==0)rt=Build(1,tot,0);
}
else
{
x1=read()^lans,y1=read()^lans,x2=read()^lans,y2=read()^lans;
printf("%d\n",lans=Query(rt,x1,x2,y1,y2));
}
}
}

第二种:类似替罪羊树,当不满足平衡因子时,把子树拍掉重构。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 200200
#define ls (t[o].ch[0])
#define rs (t[o].ch[1])
#define cmin(a,b) (a<b?a:a=b)
#define cmax(a,b) (a>b?a:a=b)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
const double alpha=0.75;
int D;
struct Node{int d[2],v;}a[MAX];
bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
struct KD_Node
{
int mn[2],mx[2],ch[2];
Node a;
int sum,size;
void clear(){mn[0]=mn[1]=mx[0]=mx[1]=a.d[0]=a.d[1]=a.v=sum=size=0;}
}t[MAX];
int Q[MAX],top;
int tot,Num;
int NewNode()
{
if(!top)return ++tot;
t[Q[top]].clear();
return Q[top--];
}
void update(int x,int y)
{
cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
}
void pushup(int o)
{
t[o].mn[0]=t[o].mx[0]=t[o].a.d[0];
t[o].mn[1]=t[o].mx[1]=t[o].a.d[1];
t[o].size=t[ls].size+t[rs].size+1;
t[o].sum=t[ls].sum+t[rs].sum+t[o].a.v;
if(ls)update(o,ls);if(rs)update(o,rs);
}
int Build(int l,int r,int nd)
{
int mid=(l+r)>>1;D=nd;
nth_element(&a[l],&a[mid],&a[r+1]);
int o=NewNode();
t[o].a=a[mid];
if(l<mid)ls=Build(l,mid-1,nd^1);else ls=0;
if(r>mid)rs=Build(mid+1,r,nd^1);else rs=0;
pushup(o);return o;
}
void kill(int o){if(ls)kill(ls);a[++Num]=t[o].a;Q[++top]=o;if(rs)kill(rs);}
void checker(int &o,int nd)
{
if(alpha*t[o].size<t[ls].size||alpha*t[o].size<t[rs].size)
Num=0,kill(o),o=Build(1,Num,nd);
}
void insert(int &o,int nd,Node a)
{
if(!o){o=NewNode();t[o].a=a;pushup(o);return;}
if(t[o].a.d[nd]<a.d[nd])insert(rs,nd^1,a);
else insert(ls,nd^1,a);
pushup(o);checker(o,nd);
}
int checksame(KD_Node a,int x1,int x2,int y1,int y2)
{
if(x1<=a.mn[0]&&a.mx[0]<=x2&&y1<=a.mn[1]&&a.mx[1]<=y2)return 1;//all
if(x2<a.mn[0]||a.mx[0]<x1)return 0;
if(y2<a.mn[1]||a.mx[1]<y1)return 0;
return 2;
}
int Query(int o,int x1,int x2,int y1,int y2)
{
int ret=0;
if(t[o].a.d[0]>=x1&&t[o].a.d[0]<=x2&&t[o].a.d[1]>=y1&&t[o].a.d[1]<=y2)
ret+=t[o].a.v;
if(ls)
{
int d=checksame(t[ls],x1,x2,y1,y2);
if(d==1)ret+=t[ls].sum;
if(d==2)ret+=Query(ls,x1,x2,y1,y2);
}
if(rs)
{
int d=checksame(t[rs],x1,x2,y1,y2);
if(d==1)ret+=t[rs].sum;
if(d==2)ret+=Query(rs,x1,x2,y1,y2);
}
return ret;
}
int N,rt;
int main()
{
N=read();
int lans=0,opt,x,y,A,x1,y1,x2,y2;
while(233)
{
opt=read();
if(opt==3)break;
if(opt==1)
{
x=read()^lans,y=read()^lans,A=read()^lans;
insert(rt,0,(Node){x,y,A});
}
else
{
x1=read()^lans,y1=read()^lans,x2=read()^lans,y2=read()^lans;
printf("%d\n",lans=Query(rt,x1,x2,y1,y2));
}
}
}

【BZOJ4066】简单题(KD-Tree)的更多相关文章

  1. BZOJ4066:简单题(K-D Tree)

    Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:   命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 ...

  2. P4148 简单题 k-d tree

    思路:\(k-d\ tree\) 提交:2次 错因:整棵树重构时的严重错误:没有维护父子关系(之前写的是假重构所以没有维护父子关系) 题解: 遇到一个新的点就插进去,如果之前出现过就把权值加上. 代码 ...

  3. [BZOJ2683][BZOJ4066]简单题

    [BZOJ2683][BZOJ4066]简单题 试题描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x ...

  4. bzoj4066: 简单题 K-Dtree

    bzoj4066: 简单题 链接 bzoj 思路 强制在线.k-dtree. 卡常啊.空间开1e6就T了. 代码 #include <bits/stdc++.h> #define my_m ...

  5. Bzoj4066 简单题

    Time Limit: 50 Sec  Memory Limit: 20 MBSubmit: 2185  Solved: 581 Description 你有一个N*N的棋盘,每个格子内有一个整数,初 ...

  6. bzoj 4066: 简单题 K-D树

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4066 题解 我们把每次的修改操作都当作二维平面上多了一个权值点 对于每组询问可以看做求一 ...

  7. BZOJ4066 简单题(KD-Tree)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  8. 【kd-tree】bzoj4066 简单题

    同p1176. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; ...

  9. bzoj 4066 & bzoj 2683 简单题 —— K-D树(含重构)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4066 https://www.lydsy.com/JudgeOnline/problem.p ...

  10. 初涉k-d tree

    听说k-d tree是一个骗分的好东西?(但是复杂度差评??? 还听说绍一的kdt常数特别小? KDT是什么 KDT的全称是k-degree tree,顾名思义,这是一种处理多维空间的数据结构. 例如 ...

随机推荐

  1. Kubernetes网络方案的三大类别和六个场景

    欢迎访问网易云社区,了解更多网易技术产品运营经验. 本文章根据网易云资深解决方案架构师 王必成在云原生用户大会上的分享整理. 今天我将分享个人对于网络方案的理解,以及网易云在交付 Kubernetes ...

  2. 微信小程序—day03

    昨日问题 接着上一篇,昨天遇到的scroll-view组件不能滚动的问题. 今天经过调试,发现是由于:图片的实际宽高,大于给image设定的宽高导致的. 解决办法: 减小图片的实际宽高,使之小于ima ...

  3. 【SpringCloud】第四篇:断路器(Hystrix)

    前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...

  4. C++0x,std::move和std::forward解析

    1.std::move 1.1std::move是如何定义的 template<typename _Tp> constexpr typename std::remove_reference ...

  5. 谜题 (Puzzle,ACM/ICPC World Finals 1993,UVa227)

    题目描述:算法竞赛入门经典习题3-5 题目思路:模拟题 #include <stdio.h> #include <string.h> #define maxn 55 char ...

  6. Window下部署MySql数据库

    官网下载地址:https://dev.mysql.com/downloads/mysql/,MySQL Community(社区版) Server 5.7.21,下载完毕后,解压文件. (1)在mys ...

  7. 数独:dfs+剪枝+位运算+排除冗余+优化搜索顺序(未完)

    和蓝桥杯以前一个题一样,但是数据加强了,博主水平有限,没做出来,先在这里记录一下,这里正解,下面是博主的超时做法.最近准备考研,不能深入学习了. 题目描述 数独是一种传统益智游戏,你需要把一个9 × ...

  8. 第一个线性回归程序(基于Jupyter)

    import pandas as pdimport seaborn as snssns.set(context="notebook", style="whitegrid& ...

  9. 测试下markdown!

    目录 目的 代码 目的 测试markdown 代码 void static void main(args String[]){ System.out.println("hollw" ...

  10. mysql唯一查询

    MySQL单一字段唯一其他字段差异性忽略查询.在使用MySQL时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返 ...