【kd-tree】bzoj3290 Theresa与数据结构

离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1。

修改操作要记录kd-tree上每个点的fa,从底向上地进行修改。

优化:若一个矩形框的sumv==0,则不进入。记录矩形框的面积时只记录“有意义”的点的(权值为0的不管)。

#include<cstdio>
#include<algorithm>
#include<stack>
#include<cstring>
using namespace std;
int f,C;
inline void R(int &x){
    C=0;f=1;
    for(;C<‘0‘||C>‘9‘;C=getchar())if(C==‘-‘)f=-1;
    for(x=0;C>=‘0‘&&C<=‘9‘;C=getchar())(x*=10)+=(C-‘0‘);
    x*=f;
}
inline void P(int x){
    if(x<10)putchar(x+‘0‘);
    else{P(x/10);putchar(x%10+‘0‘);}
}
stack<int>zhan;
#define N 100001
#define KD 3
int dn,n,root,m,qp[2][KD],idn;
struct Node
{
    int ch[2],w,minn[KD],maxx[KD],p[KD],sumv,id;
    void Init()
      {
        sumv=w;
        for(int i=0;i<KD;++i)
          minn[i]=maxx[i]=p[i];
      }
}T[N];
bool operator < (const Node &a,const Node &b){return a.p[dn] < b.p[dn];}
inline void pushup(const int &rt)
{
    T[rt].sumv=T[rt].w;
    for(int i=0;i<2;++i)
      if(T[rt].ch[i]/* && T[T[rt].ch[i]].sumv*/)
        {
          T[rt].sumv+=T[T[rt].ch[i]].sumv;
          for(int j=0;j<KD;++j)
            {
              T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]);
              T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]);
            }
        }
}
int buildtree(int l=1,int r=n,int d=0)
{
    dn=d;
    int m=(l+r>>1);
    nth_element(T+l,T+m,T+r+1);
    T[m].Init();
    if(l!=m) T[m].ch[0]=buildtree(l,m-1,(d+1)%KD);
    if(m!=r) T[m].ch[1]=buildtree(m+1,r,(d+1)%KD);
    pushup(m);
    return m;
}
inline bool Inside(const int &o)
{
    for(int i=0;i<KD;++i)
      if(qp[0][i] > T[o].p[i] || T[o].p[i] > qp[1][i])
        return 0;
    return 1;
}
inline bool AllInside(const int &o)
{
    for(int i=0;i<KD;++i)
      if(qp[0][i] > T[o].minn[i] || T[o].maxx[i] > qp[1][i])
        return 0;
    return 1;
}
inline bool Cross(const int &o)
{
    for(int i=0;i<KD;++i)
      if(qp[0][i] > T[o].maxx[i] || T[o].minn[i] > qp[1][i])
        return 0;
    return 1;
}
int ans;
inline void Query(int rt=root)
{
    if(Inside(rt)) ans+=T[rt].w;
    for(int i=0;i<2;++i)
      if(T[rt].ch[i] && Cross(T[rt].ch[i]))
        {
          if(AllInside(T[rt].ch[i]))
            ans+=T[T[rt].ch[i]].sumv;
          else if(T[T[rt].ch[i]].sumv)
            Query(T[rt].ch[i]);
        }
}
int val;
char op[N][7];
int dian[N][KD],rs[N],ids[N],ma[N],fa[N];
void Update()
{
    int U=ma[idn];
    T[U].w+=val;
    T[U].sumv+=val;
    U=fa[U];
    while(U)
      {
        T[U].sumv=T[U].w+T[T[U].ch[0]].sumv+T[T[U].ch[1]].sumv;
//      pushup(U);
        U=fa[U];
      }
}
int main()
{
//  freopen("theresa9.in","r",stdin);
//  freopen("bzoj3290.out","w",stdout);
    R(n);
    for(int i=1;i<=n;++i)
      {
        R(T[i].p[0]); R(T[i].p[1]); R(T[i].p[2]);
        T[i].id=i;
        T[i].w=1;
      }
    R(m);
    for(int i=1;i<=m;++i)
      {
        scanf("%s",op[i]);
        if(op[i][0]==‘A‘)
          {
            ++n;
            R(T[n].p[0]); R(T[n].p[1]); R(T[n].p[2]);
            T[n].id=n;
            ids[i]=n;
            zhan.push(n);
          }
        else if(op[i][0]==‘Q‘)
          {
            R(dian[i][0]); R(dian[i][1]); R(dian[i][2]); R(rs[i]);
          }
        else
          {
            ids[i]=zhan.top();
            zhan.pop();
          }
      }
    root=(1+n>>1);
    buildtree();
    for(int i=1;i<=n;++i)
      {
        ma[T[i].id]=i;
        for(int j=0;j<2;++j)
          if(T[i].ch[j])
            fa[T[i].ch[j]]=i;
      }
    for(int i=1;i<=m;++i)
      if(op[i][0]==‘A‘)
        {
          idn=ids[i];
          val=1;
          Update();
        }
      else if(op[i][0]==‘Q‘)
        {
          memcpy(qp[0],dian[i],sizeof(qp[0]));
          for(int j=0;j<KD;++j)
            qp[1][j]=qp[0][j]+rs[i];
          ans=0;
          Query();
//        printf("%d\n",ans);
          P(ans),puts("");
        }
      else
        {
          idn=ids[i];
          val=-1;
          Update();
        }
    return 0;
}
时间: 2024-11-05 19:45:48

【kd-tree】bzoj3290 Theresa与数据结构的相关文章

bzoj3290: Theresa与数据结构

Description [题目背景] Theresa是个爱思考的女孩…… [问题描述] 这是个复杂的世界.人类社会,自然界,还有地球之外的银河…… 每一天日出日落,人来人往,步履匆匆.究竟是为什么呢?那支配着一切的至高无上的法则又是否存在呢?Theresa知道,这个问题并不是一朝一夕就可以解答的,只有在仔细.深入的观察和思考以后,才有可能将所有支离破碎的线索联系起来,从而隐约窥见真实的答案. 于是,Theresa经常思考生活中遇到的大大小小的问题.为什么港台出版的书籍里印刷的汉字她一个也不认识呢

[转载]kd tree

[本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树

k-d tree算法详解

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 1.应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树就是其中一种. 索引结构中相似性查询有两种基本的方式:一种是范围查询(range searches),另一种是K近邻查询

k-d tree算法

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树就是其中一种. 索引结构中相似性查询有两种基本的方式:一种是范围查询(range searches),另一种是K近邻查询(K

Google interview question: k-nearest neighbor (k-d tree)

Question: You are given information about hotels in a country/city. X and Y coordinates of each hotel are known. You need to suggest the list of nearest hotels to a user who is querying from a particular point (X and Y coordinates of the user are giv

k-d tree

先以一个简单直观的实例来介绍k-d树算法.假设有6个二维数据点{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间内(如图2中黑点所示).k-d树算法就是要确定图2中这些分割空间的分割线(多维空间即为分割平面,一般为超平面).下面就要通过一步步展示k-d树是如何确定这些分割线的. k-d树算法可以分为两大部分,一部分是有关k-d树本身这种数据结构建立的算法,另一部分是在建立的k-d树上如何进行最邻近查找的算法. 构造kd树 kd树是一种对k维空间中的实例

【BZOJ-2648&amp;2716】SJY摆棋子&amp;天使玩偶 KD Tree

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000

KD tree

Kd-树 其实是K-dimension tree的缩写,是对数据点在k维空间中划分的一种数据结构.其实,Kd-树是一种平衡二叉树. 举一示例: 假设有六个二维数据点 = {(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间中.为了能有效的找到最近邻,Kd-树采用分而治之的思想,即将整个空间划分为几个小部分.六个二维数据点生成的Kd-树的图为: 对于拥有n个已知点的kD-Tree,其复杂度如下: 构建:O(log2n) 插入:O(log n) 删除:O(l

k-d tree学习总结

本文转载自http://blog.csdn.net/zhjchengfeng5/article/details/7855241# 首先来一个问题: 给定平面上一个点集 E ,还有一个定点 V ,怎么在一群点中找出一个点 U,使得 V 与 U 的距离最近(欧几里得距离)? 当然,我们能够想到一种做法:枚举 E 中所有的点,找出它们中距离V 最近的点 U. 但是,假设现在有两个点集 E1 与 E2 ,对于 E2 中每一个点 Vi ,找出一个在E1 中的一个点 Ui,使得 Vi 到 Ui 的距离最短,