BZOJ 4066 kd-tree 矩形询问求和

第一次遇见强制在线的题目 每个操作都和前面的ans有关 所以不能直接离线做

在这个问题中 kdtree更像一个线段树在一维单点修改区间询问的拓展一样

如果区间被询问区间完全包含 就不用继续递归

插入时如果该点已被修改 就不用建新点

由于kdtree是一个二叉搜索树 所以如果数据构造 是可以卡出一条链的 所以需要在插入一定点数之后开始重构这个kdtree 使深度维持在一个可控范围内

因为写错了in_it函数找了一天bug

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<queue>
#include<string>
using namespace std;
#define L long long
const int INF = 999999999 ;
const int maxn = 200050 ;
int n , root , cmp_d , m;
struct node {
    int d[2] , Max[2] , Min[2] ;
    int l , r ;
    int sum ;
    int z ;
}a[maxn];
int x, y , X;
int x1, x2, y11 ,y2 ;
bool cmp(node a , node b ){return ((a.d[cmp_d] < b.d[cmp_d]) || (a.d[cmp_d] == b.d[cmp_d] && a.d[!cmp_d] < b.d[!cmp_d])) ;}
void up(int p , int k) {
    a[p].Max[0] = max(a[p].Max[0] , a[k].Max[0]) ;
    a[p].Max[1] = max(a[p].Max[1] , a[k].Max[1]) ;
    a[p].Min[0] = min(a[p].Min[0] , a[k].Min[0]) ;
    a[p].Min[1] = min(a[p].Min[1] , a[k].Min[1]) ;
    a[p].sum += a[k].sum ;
}
int build(int l , int r , int D){
    int mid = (l+r) / 2 ;
    cmp_d = D;
    nth_element(a+1+l,a+1+mid,a+1+r,cmp) ;
    a[mid].Max[0] = a[mid].Min[0] = a[mid].d[0] ;
    a[mid].Max[1] = a[mid].Min[1] = a[mid].d[1] ;
    a[mid].sum = a[mid].z ;
    if(l != mid) a[mid].l = build(l,mid-1,D^1) ; else a[mid].l = 0;
    if(r != mid) a[mid].r = build(mid+1,r,D^1) ; else a[mid].r = 0;
    if(a[mid].l)up(mid,a[mid].l) ;
    if(a[mid].r)up(mid,a[mid].r) ;
    return mid ;
}
void inse(int x , int y , int X) {
    int p = root ;
    int D = 0 ;
    while(true) {
        if(x > a[p].Max[0]) a[p].Max[0] = x ;
        if(x < a[p].Min[0]) a[p].Min[0] = x ;
        if(y > a[p].Max[1]) a[p].Max[1] = y ;
        if(y < a[p].Min[1]) a[p].Min[1] = y ;
        a[p].sum += X ;
        if(x == a[p].d[0] && y == a[p].d[1]) {
            a[p].z += X ;
            return ;
        }
        else {
            if(D == 0) {
                if(x <= a[p].d[0]) {
                    if(a[p].l) p = a[p].l ;
                    else {
                        n ++ ;
                        a[n].l = a[n].r = 0 ;
                        a[n].Max[0] = a[n].Min[0] = a[n].d[0] = x ;
                        a[n].Min[1] = a[n].Max[1] = a[n].d[1] = y ;
                        a[n].sum = a[n].z = X ;
                        a[p].l = n ;
                        return ;
                    }
                }
                else {
                    if(a[p].r) p = a[p].r ;
                    else {
                        n ++ ;
                        a[n].l = a[n].r = 0 ;
                        a[n].Max[0] = a[n].Min[0] = a[n].d[0] = x ;
                        a[n].Min[1] = a[n].Max[1] = a[n].d[1] = y ;
                        a[n].sum = a[n].z = X ;
                        a[p].r = n ;
                        return ;
                    }
                }
            }
            else {
                if(y <= a[p].d[1]) {
                    if(a[p].l) p = a[p].l ;
                    else {
                        n ++ ;
                        a[n].l = a[n].r = 0 ;
                        a[n].Max[0] = a[n].Min[0] = a[n].d[0] = x ;
                        a[n].Min[1] = a[n].Max[1] = a[n].d[1] = y ;
                        a[n].sum = a[n].z = X ;
                        a[p].l = n ;
                        return ;
                    }
                }
                else {
                    if(a[p].r) p = a[p].r ;
                    else {
                        n ++ ;
                        a[n].l = a[n].r = 0 ;
                        a[n].Max[0] = a[n].Min[0] = a[n].d[0] = x ;
                        a[n].Min[1] = a[n].Max[1] = a[n].d[1] = y ;
                        a[n].sum = a[n].z = X ;
                        a[p].r = n ;
                        return ;
                    }
                }
            }
        }
        D ^= 1 ;
    }
}
bool in_it(int p , int x1,int y11,int x2 , int y2 ){
    if(x1 <= a[p].Min[0] && x2 >= a[p].Max[0] && y11 <= a[p].Min[1] && y2 >= a[p].Max[1]) {
        return true ;
    }
    return false ;
}
bool rea_out(int p , int x1 , int y11 , int x2 , int y2 ){
    if(x2 < a[p].Min[0] || x1 > a[p].Max[0] || y2 < a[p].Min[1] || y11 > a[p].Max[1]) return true;
    return false ;
}
int ans ;
void ask(int p) {
    if(rea_out(p , x1 , y11 , x2 , y2)) return ;
    if(in_it(p , x1 , y11 , x2 , y2)) {
        ans += a[p].sum ;
        return ;
    }
    if(a[p].d[0] >= x1 && a[p].d[0] <= x2 && a[p].d[1] >= y11 && a[p].d[1] <= y2) {
        ans += a[p].z ;
    }
    if(a[p].l){
        ask(a[p].l);
    }
    if(a[p].r){
        ask(a[p].r);
    }
}
int main(){
    scanf("%d",&m);
    int op;
    int last=0;
    n = 0;
    while(~scanf("%d",&op)){
        if(op == 3)break;
        if(op == 1) {
            scanf("%d%d%d",&x,&y,&X) ;
            x ^= last;
            y ^= last;
            X ^= last;
            if(n == 0) {
                n ++ ;
                a[n].d[0] = x ; a[n].d[1] = y ;
                a[n].z = X ;
                a[n].sum = X ;
                root = build(1,n,0) ;
            }
            else {
                inse(x,y,X) ;
            }
            if(n % 5000 == 0) {
                root = build(1,n,0) ;
            }
        }
        else {
            scanf("%d%d%d%d",&x1,&y11,&x2,&y2) ;
            x1 ^= last;
            y11 ^= last;
            x2 ^= last;
            y2 ^= last;
            ans = 0;
            if(n>0)
                ask(root);
            else ans = 0 ;
            last = ans ;
            printf("%d\n",ans) ;
        }
    }
}

  

时间: 2024-11-10 00:57:50

BZOJ 4066 kd-tree 矩形询问求和的相关文章

BZOJ 2648: SJY摆棋子(K-D Tree)

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

BZOJ 1941: [Sdoi2010]Hide and Seek(k-d Tree)

Time Limit: 16 Sec  Memory Limit: 162 MBSubmit: 1712  Solved: 932[Submit][Status][Discuss] Description 小猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏. 但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义

k-d tree 学习笔记

以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac/blog/1693 https://en.wikipedia.org/wiki/K-d_tree http://homes.ieu.edu.tr/hakcan/projects/kdtree/kdTree.html k-d tree就是一个把一个平面(或超平面)划分的东西- 例如一维情况就是在划分

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维空间中的实例

k-d tree模板练习

1. [BZOJ]1941: [Sdoi2010]Hide and Seek 题目大意:给出n个二维平面上的点,一个点的权值是它到其他点的最长距离减最短距离,距离为曼哈顿距离,求最小权值.(n<=500,000) 思路:k-d tree裸题. #include<cstdio> #include<algorithm> using namespace std; inline int read() { int x;char c; while((c=getchar())<'0'

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 的距离最短,

简单题(K-D Tree)

简单题不简单-- 我们把单点加操作改成插入一个权值为增加量的点,将问题转化成询问一个矩阵中所有点的和,用 \(K-D\ Tree\) 维护,时间复杂度 \(O(n\sqrt{n})\) \(Code\ Below:\) // luogu-judger-enable-o2 #include <bits/stdc++.h> using namespace std; const int maxn=500000+10; const double alpha=0.75; int n,D,rt,cnt,t

[转载]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近邻查询