由于网上的其它博客对初学者非常不友好,所以我就来写一篇博客帮助萌新们快速入门树套树啦。所谓线段树套线段树就是在第一棵线段树的每一个结点上再开一颗线段树,第一棵线段树用来维护第一维的数据,再用第一棵线段树上新开的线段树来维护第二维的数据。是不是没听懂呢,下面我们直接上图:

这就是树套树大概的模样,横线上面是第一棵线段树,下面是对第一棵线段树的每一个结点新开的线段树,就像是每一个点内都套着一棵线段树一样,那么二维线段树就可以用来维护平面信息下面看一道例题:
陌上花开
首先对第一维进行排序,然后用树套树进行处理,具体来讲,我们将第二维和第三维视为平面中的一点的坐标,然后每次单点修改,二维区间查询,就是统计一个矩形内部的元素之和,我们对第一棵线段树的每一个结点进行修改是实际上就是对这个结点中套着的线段树进行修改,对套着的线段树进行修改是才是和一维线段树一样的修改方法,另外,树套树由于占用空间过大,需要使用动态开点的方法,话不多说,上代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 20000005
using namespace std;int read()
{int x=1,res=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}struct node{int a,b,c;
}g[maxn];
struct tree{int l,r;
}t1[maxn],t2[maxn];
int n,p,ans[maxn],tot1,tot2,root1,root[maxn],d[maxn],last;
bool cmp(node a,node b) {return a.a<b.a;}void _2nd_modify(int &k,int l,int r,int i)
{if(!k) k=++tot2;d[k]+=1;if(l==r) return;int mid=(l+r)>>1;if(mid>=g[i].c) _2nd_modify(t2[k].l,l,mid,i);else _2nd_modify(t2[k].r,mid+1,r,i);
}void _1st_modify(int &k,int l,int r,int i)
{if(!k) k=++tot1;_2nd_modify(root[k],1,p,i);if(l==r) return;int mid=(l+r)>>1;if(mid>=g[i].b) _1st_modify(t1[k].l,l,mid,i);else _1st_modify(t1[k].r,mid+1,r,i);
}int _2nd_query(int k,int l,int r,int x,int y,int i)
{if(k==0) return 0;if(x<=l&&r<=y) return d[k];int mid=(l+r)>>1,res=0;if(x<=mid) res+=_2nd_query(t2[k].l,l,mid,x,y,i);if(mid+1<=y) res+=_2nd_query(t2[k].r,mid+1,r,x,y,i);return res;
}int _1st_query(int k,int l,int r,int x,int y,int i)
{if(k==0) return 0;if(x<=l&&r<=y) return _2nd_query(root[k],1,p,1,g[i].c,i);int mid=(l+r)>>1,res=0;if(x<=mid) res+=_1st_query(t1[k].l,l,mid,x,y,i);if(mid+1<=y) res+=_1st_query(t1[k].r,mid+1,r,x,y,i);return res;
}int main()
{n=read();p=read();for(int i=1;i<=n;i++){g[i].a=read();g[i].b=read();g[i].c=read();}sort(g+1,g+1+n,cmp);last=1;for(int i=1;i<=n;i++){_1st_modify(root1,1,p,i);if(g[i+1].a!=g[i].a) {for(int j=last;j<=i;j++)ans[_1st_query(root1,1,p,1,g[j].b,j)-1]++;last=i+1;}}for(int i=0;i<n;i++) printf("%d\n",ans[i]);
}

再看一道题:
GDCPC 2021 K ~~  Kera’s line segment
还是将问题转换为平面问题,然后用二维线段树维护平面最大和最小值即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 20000005
using namespace std;int read()
{int x=1,res=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')x=-1;c=getchar();}while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}return res*x;
}struct nn{int Max,Min;
};
struct node{int a,b,c;
}g[maxn];
struct tree{int l,r,Min,Max;
}t1[maxn],t2[maxn];
int n,tot1,tot2,root1,root[maxn],last,op,m,aa,bb,cc;void _2nd_modify(int &k,int l,int r,int i)
{if(!k) k=++tot2;t2[k].Max=max(t2[k].Max,g[i].c);t2[k].Min=min(t2[k].Min,g[i].c);if(l==r) return;int mid=(l+r)>>1;if(mid>=g[i].b) _2nd_modify(t2[k].l,l,mid,i);else _2nd_modify(t2[k].r,mid+1,r,i);
}void _1st_modify(int &k,int l,int r,int i)
{if(!k) k=++tot1;_2nd_modify(root[k],1,3000,i);if(l==r) return;int mid=(l+r)>>1;if(mid>=g[i].a) _1st_modify(t1[k].l,l,mid,i);else _1st_modify(t1[k].r,mid+1,r,i);
}nn _2nd_query(int k,int l,int r,int x,int y)
{if(k==0) return (nn){0,(int)2e9};if(x<=l&&r<=y) return (nn){t2[k].Max,t2[k].Min};int mid=(l+r)>>1,res1=0,res2=2e9;if(x<=mid) {res1=max(res1,_2nd_query(t2[k].l,l,mid,x,y).Max);res2=min(res2,_2nd_query(t2[k].l,l,mid,x,y).Min);}if(mid+1<=y){res1=max(res1,_2nd_query(t2[k].r,mid+1,r,x,y).Max);res2=min(res2,_2nd_query(t2[k].r,mid+1,r,x,y).Min);}return (nn){res1,res2};
}nn _1st_query(int k,int l,int r,int x,int y)
{if(k==0) return (nn){0,(int)2e9};if(x<=l&&r<=y) return _2nd_query(root[k],1,3000,x,y);int mid=(l+r)>>1,res1=0,res2=2e9;if(x<=mid){res1=max(res1,_1st_query(t1[k].l,l,mid,x,y).Max);res2=min(res2,_1st_query(t1[k].l,l,mid,x,y).Min);}if(mid+1<=y){res1=max(res1,_1st_query(t1[k].r,mid+1,r,x,y).Max);res2=min(res2,_1st_query(t1[k].r,mid+1,r,x,y).Min);}return (nn){res1,res2};
}int main()
{n=read();m=read();for(int i=1;i<=1e7;i++)t2[i].Min=2e9;for(int i=1;i<=n;i++){g[i].a=read();g[i].b=read();g[i].c=read();_1st_modify(root1,1,3000,i);}last=0;for(int i=1;i<=m;i++){op=read();if(op==1){aa=read();bb=read();cc=read();aa=aa^last;bb=bb^last;g[i].a=aa;g[i].b=bb;g[i].c=cc;_1st_modify(root1,1,3000,i);}if(op==2){aa=read();bb=read();
//          printf("%d %d\n",aa,bb);aa=aa^last;bb=bb^last;nn u=_1st_query(root1,1,3000,aa,bb);
//          printf("max:%d min:%d\n",u.Max,u.Min);if(u.Min==2e9) u.Min=0;last=u.Max-u.Min;printf("%d\n",last);}}return 0;
}

二维线段树(线段树套线段树)相关推荐

  1. BZOJ.4553.[HEOI2016TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j)if(a[j ...

  2. H - Hello Ms. Ze(树状数组套主席树,线段树上二分)

    H - Hello Ms. Ze 给定nnn种不同的材料,第iii种材料有aia_iai​个,有mmm个操作,操作分为两类: 把第xxx种材料修改为yyy个, 只用[l,r][l, r][l,r]区间 ...

  3. 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树

    I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...

  4. BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...

  5. zoj 2112 树状数组 套主席树 动态求区间 第k个数

    总算是把动态求区间第k个数的算法看明白了. 在主席树的基础上,如果有修改操作,则要通过套树状数组来实现任意区间求第k小的问题. 刚开始看不明白什么意思,现在有一点理解.树状数组的每个元素是一个线段树, ...

  6. (三叉字典树)二叉树套字典树

    看了道题,是要写个字典树排序的,但又不局限于二十六个字母,于是来了个三叉字典树(二叉树套字典树).最差时间复杂度是trie树的常数倍,空间比trie树省得多了. #include<cstdio& ...

  7. ICPC 徐州 H Yuuki and a problem (树状数组套主席树)

    Yuuki and a problem 先不管第一问的修改操作,考虑如何达到第二问的查询操作, 题目要我们给出一个区间[l,r][l, r][l,r]中,不能通过权值+++得到的最小的数字是什么, 假 ...

  8. #279. [SYZOI Round1] 滑稽♂树(树状数组套主席树)

    #279. [SYZOI Round1] 滑稽♂树 子树上的问题,考虑dfsdfsdfs序,第kkk大,可以用主席树嘛,支持修改,那就树状数组上套主席树,参考P4175 [CTSC2008]网络管理( ...

  9. 【BZOJ1901】Dynamic Rankings,树状数组套主席树

    Time:2016.05.09 Author:xiaoyimi 转载注明出处谢谢 传送门(权限) 题面 1901: Zju2112 Dynamic Rankings Time Limit: 10 Se ...

  10. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

最新文章

  1. 分片提升容量难度大,时间长,故而Vitalik提出使用BCH或者ETC作为以太坊数据层
  2. python图表之pygal入门篇
  3. Cannot send session cache limiter - headers already sent错误解决方法
  4. 错误 未找到引用源_你不理解的EXCEL函数中常见的错误值,都在这里
  5. Linux下对Verilog文件进行leda检错
  6. 数据结构与算法之转圈打印矩阵和旋转正方形矩阵
  7. 喷水装置(一)--nyoj题目6
  8. html5编辑文档,HTML5带各种趣味动画的文本编辑器
  9. nginx搭建基于http协议的视频点播服务器
  10. python numpy常用操作、Numpy 多维数组、矩阵相乘、矩阵乘以向量
  11. 【Elasticsearch】Elasticsearch:Searchable snapshot - 可搜索的快照
  12. 更改oracle字符集为utf_oracle字符集AL16UTF16改为ZHS16GBK
  13. 浮动元素横排居中显示及浏览器兼容性处理
  14. mysql命令:set sql_log_bin=on/off
  15. 怎么把线稿提取出来_【PS技巧】如何用PS快速提取线稿?
  16. MOQL—过滤器(Filter)
  17. CSS布局:图片在DIV中上下左右居中(水平和垂直都居中)
  18. linux 卸载opera,Ubuntu中安装Opera 55 浏览器
  19. PIC16F887 单片机 proteus 红外遥控灯光控制系统
  20. 呼叫中心系统的解决方案

热门文章

  1. ts 正负条形图 组件_手把手教你使用ggplot2绘制条形图
  2. 自动驾驶之-MATLAB环境下基于深度学习的语义分割
  3. vb与c语言数组传递,在VB中调用C/C++语言编写的dll,数组参数的传递
  4. 基于Android Tv制作一个Tv桌面(三)
  5. windows 截图软件——sharex 截图软件的天花板 并且是免费开源的。
  6. 服务端渲染和客户端渲染
  7. 华为畅享20为什么没有计算机,华为畅享20有没有红外线?华为畅享20有NFC功能吗...
  8. C++输出流cout的执行顺序问题
  9. 删软件怎么用计算机管理员删除,win10卸载软件需要管理员权限,卸载软件没有管理员权限...
  10. 月下夜想曲200.6(攻略3)