OSDN Git Service

Update k-dtree.md
author雷蒻 <34390285+hsfzLZH1@users.noreply.github.com>
Sun, 28 Jul 2019 08:25:08 +0000 (16:25 +0800)
committerGitHub <noreply@github.com>
Sun, 28 Jul 2019 08:25:08 +0000 (16:25 +0800)
docs/ds/k-dtree.md

index 8acb859..26b2ec1 100644 (file)
@@ -216,4 +216,113 @@ k-D Tree 具有二叉搜索树的形态,二叉搜索树上的每个结点都
 
 ## 高维空间上的操作
 
+
+???+note " 例题[luogu P4148 简单题](https://www.luogu.org/problem/P4148)"
+
+    在一个初始值全为 $0$ 的 $n\times n$ 的二维矩阵上,进行 $q$ 次操作,每次操作为以下两种之一:
+    
+    1.  `1 x y A` :将坐标 $(x,y)$ 上的数加上 $A$ 。
+    2.  `2 x1 y1 x2 y2` : 输出以 $(x1,y1)$ 为左下角, $(x2,y2)$ 为右上角的矩形内(包括矩形边界)的数字和。
+    
+    强制在线。内存限制 `20M` 。保证答案及所有过程量在 `int` 范围内。
+
+    $1\le n\le 500000 , 1\le q\le 200000$
+    
+20M 的空间卡掉了所有树套树,强制在线卡掉了 CDQ 分治,只能使用 k-D Tree 。
+
+构建 2-D Tree ,支持两种操作:添加一个 $2$ 维点;查询矩形区域内的所有点的权值和。可以使用 **带重构** 的 k-D Tree 实现。
+
+在查询矩形区域内的所有点的权值和时,仍然需要记录子树内每一维度上的坐标的最大值和最小值。如果当前子树对应的矩形与所求矩形没有交点,则不继续搜索其子树;如果当前子树对应的矩形完全包含在所求矩形内,返回当前子树内所有点的权值和;否则,判断当前点是否在所求矩形内,更新答案并递归在左右子树中查找答案。
+
+已经证明,如果在 $2-D$ 树上进行矩阵查询操作,已经被完全覆盖的子树不会继续查询,则单次查询时间复杂度是期望 $O(\log_2 n)$ ,最坏 $O(\sqrt n)$ 的。将结论扩展到 $k$ 维的情况,则最坏时间复杂度是 $O(n^{1-\frac 1 k})$ 的。
+
+??? "参考代码"
+
+    ```cpp
+    #include<cstdio>
+    #include<cstring>
+    #include<algorithm>
+    using namespace std;
+    const int maxn=200010;
+    int n,op,xl,xr,yl,yr,lstans;
+    struct node{int x,y,v;}s[maxn];
+    bool cmp1(int a,int b){return s[a].x<s[b].x;}
+    bool cmp2(int a,int b){return s[a].y<s[b].y;}
+    double a=0.725;
+    int rt,cur,d[maxn],lc[maxn],rc[maxn],L[maxn],R[maxn],D[maxn],U[maxn],siz[maxn],sum[maxn];
+    int g[maxn],t;
+    void print(int x){if(!x)return;print(lc[x]);g[++t]=x;print(rc[x]);}
+    void maintain(int x)
+    {
+       siz[x]=siz[lc[x]]+siz[rc[x]]+1;
+       sum[x]=sum[lc[x]]+sum[rc[x]]+s[x].v;
+       L[x]=R[x]=s[x].x;D[x]=U[x]=s[x].y;
+       if(lc[x])L[x]=min(L[x],L[lc[x]]),R[x]=max(R[x],R[lc[x]]),D[x]=min(D[x],D[lc[x]]),U[x]=max(U[x],U[lc[x]]);
+       if(rc[x])L[x]=min(L[x],L[rc[x]]),R[x]=max(R[x],R[rc[x]]),D[x]=min(D[x],D[rc[x]]),U[x]=max(U[x],U[rc[x]]);
+    }
+    int build(int l,int r)
+    {
+       if(l>r)return 0;
+               int mid=(l+r)>>1;
+       double av1=0,av2=0,va1=0,va2=0;
+       for(int i=l;i<=r;i++)av1+=s[g[i]].x,av2+=s[g[i]].y;
+       av1/=(r-l+1);av2/=(r-l+1);
+       for(int i=l;i<=r;i++)va1+=(av1-s[g[i]].x)*(av1-s[g[i]].x),va2+=(av2-s[g[i]].y)*(av2-s[g[i]].y);
+       if(va1>va2)nth_element(g+l,g+mid,g+r+1,cmp1),d[g[mid]]=1;
+       else nth_element(g+l,g+mid,g+r+1,cmp2),d[g[mid]]=2;
+       lc[g[mid]]=build(l,mid-1);rc[g[mid]]=build(mid+1,r);
+       maintain(g[mid]);return g[mid];
+    }
+    void rebuild(int&x){t=0;print(x);x=build(1,t);}
+    bool bad(int x){return a*siz[x]<=(double)max(siz[lc[x]],siz[rc[x]]);}
+    void insert(int&x,int v)
+    {
+       if(!x){x=v;maintain(x);return;}
+       if(d[x]==1){if(s[v].x<=s[x].x)insert(lc[x],v);else insert(rc[x],v);}
+       else{if(s[v].y<=s[x].y)insert(lc[x],v);else insert(rc[x],v);}
+       maintain(x);
+       if(bad(x))rebuild(x);
+    }
+    int query(int x)
+    {
+       if(!x||xr<L[x]||xl>R[x]||yr<D[x]||yl>U[x])return 0;
+       if(xl<=L[x]&&R[x]<=xr&&yl<=D[x]&&U[x]<=yr)return sum[x];
+       int ret=0;
+       if(xl<=s[x].x&&s[x].x<=xr&&yl<=s[x].y&&s[x].y<=yr)ret+=s[x].v;
+       return query(lc[x])+query(rc[x])+ret;
+    }
+    int main()
+    {
+       scanf("%d",&n);
+       while(~scanf("%d",&op))
+       {
+               if(op==1)
+               {
+                       cur++,scanf("%d%d%d",&s[cur].x,&s[cur].y,&s[cur].v);
+                       s[cur].x^=lstans;s[cur].y^=lstans;s[cur].v^=lstans;
+                       insert(rt,cur);
+               }
+               if(op==2)
+               {
+                       scanf("%d%d%d%d",&xl,&yl,&xr,&yr);
+                       xl^=lstans;yl^=lstans;xr^=lstans;yr^=lstans;
+                       printf("%d\n",lstans=query(rt));
+               }
+               if(op==3)return 0;
+       }
+    }
+    ```
+
 ## 习题
+
+[luogu P2479 \[SDOI2010\]捉迷藏](https://www.luogu.org/problem/P2479)
+
+[luogu P4169 \[Violet\]天使玩偶/SJY摆棋子](https://www.luogu.org/problem/P4169)
+
+[luogu P2093 \[国家集训队\]JZPFAR](https://www.luogu.org/problem/P2093)
+
+[luogu P4390 \[BOI2007\]Mokia 摩基亚](https://www.luogu.org/problem/P4390)
+
+[luogu P4475 巧克力王国](https://www.luogu.org/problem/P4475)
+
+[luogu P3769 \[CH弱省胡策R2\]TATT](https://www.luogu.org/problem/P3769)