二维线段树->树套树
现在上真正的二维线段树 毕竟 刚刚那个是卡常 过题我们现在做一个更高级的做法二维线段树。
大体上维护一颗x轴线段树 然后在每个节点的下方再吊一颗维护y轴的线段树那么此时我们整个平面就被我们玩好了。
这样形成二维线段树比刚才的要 合理多了。
写起来 不免有点蒙蔽...然后突然就顿悟了 其实每次我们对于区间的修改大概就是先把x属于x轴的那一段区间给拎出来然后在那个区间之中把那个区间的y轴线段树给修改掉。

还是刚刚那道题 这次是MLE 了 理论上二维线段树空间复杂度 (MAXN<<2)^2这个复杂度 可是正中下怀的MLE了 开小了一点就可以过了。
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cstring>
#include<string>
#include<ctime>
#include<cctype>
#include<cstdio>
#include<utility>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
#include<bitset>
#include<vector>
#include<algorithm>
#include<cstdlib>
#define INF 1000000000
#define ll long long
#define mx(p) t[p].mx
#define tag(p) t[p].tag
#define RE register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
RE int x=,f=;RE char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
const int MAXN=;
int n,m,Q;
int qx,xx,qy,yy,h;
inline int max(int x,int y){return x>y?x:y;}
struct wy
{
int mx[MAXN],tag[MAXN];
inline void change(int p,int l,int r,int x,int y,int k)
{
mx[p]=max(mx[p],k);
if(l==x&&r==y)
{
tag[p]=max(tag[p],k);
return;
}
int mid=(l+r)>>;
if(y<=mid)change(p<<,l,mid,x,y,k);
else
{
if(x>mid)change(p<<|,mid+,r,x,y,k);
else change(p<<,l,mid,x,mid,k),change(p<<|,mid+,r,mid+,y,k);
}
}
inline int ask(int p,int l,int r,int x,int y)
{
if(l==x&&r==y)return mx[p];
int mid=(l+r)>>,ans=tag[p];
if(y<=mid)ans=max(ans,ask(p<<,l,mid,x,y));
else
{
if(x>mid)ans=max(ans,ask(p<<|,mid+,r,x,y));
else ans=max(ans,max(ask(p<<,l,mid,x,mid),ask(p<<|,mid+,r,mid+,y)));
}
return ans;
}
};
struct tx
{
wy mx[MAXN],tag[MAXN];
inline void change(int p,int l,int r,int x,int y,int k)
{
mx[p].change(,,m,qy,yy,k);
if(l==x&&r==y)
{
tag[p].change(,,m,qy,yy,k);
return;
}
int mid=(l+r)>>;
if(y<=mid)change(p<<,l,mid,x,y,k);
else
{
if(x>mid)change(p<<|,mid+,r,x,y,k);
else change(p<<,l,mid,x,mid,k),change(p<<|,mid+,r,mid+,y,k);
}
}
inline int ask(int p,int l,int r,int x,int y)
{
if(l==x&&r==y)return mx[p].ask(,,m,qy,yy);
int mid=(l+r)>>,ans=tag[p].ask(,,m,qy,yy);
if(y<=mid)ans=max(ans,ask(p<<,l,mid,x,y));
else
{
if(x>mid)ans=max(ans,ask(p<<|,mid+,r,x,y));
else
{
ans=max(ans,ask(p<<,l,mid,x,mid));
ans=max(ans,ask(p<<|,mid+,r,mid+,y));
}
}
return ans;
}
}T;
int main()
{
freopen("1.in","r",stdin);
n=read();m=read();Q=read();
while(Q--)
{
xx=read();yy=read();h=read();
qx=read()+;qy=read()+;
xx=qx+xx-;yy=qy+yy-;
int ans=T.ask(,,n,qx,xx);
T.change(,,n,qx,xx,ans+h);
}
qx=;qy=;xx=n;yy=m;
printf("%d\n",T.ask(,,n,qx,xx));
return ;
}
操作还是不太熟悉 觉得这个可持久化有点神仙没写过有点 怀疑 不过正确性 和 合理性都是比较显然的。
简述一下大体的思路吧 首先对x轴开一棵线段树然后 在x轴的这颗线段树每个节点处都吊着一棵y轴的线段树。
下传修改标记 的时候 对于到过路径上的所有的节点都应该修改值 因为这是标记所致 到了锁定的区间之后标记永久化 对这个tag打上标记 而对内部的y轴线段树也进行一次标记永久化。
通俗的来说 内外线段树处理方式一模一样。为什么不能下传标记 显然的是我们对于外层线段树的修改 在自己的内部是无法下传的 因为标记是无法合并的 比如说 ta 要修改1 n 1 2这个区间ta又要修改1 n 1 3这个区间显然这两个区间在x线段树上是对等的在y线段树上可并不对等所以这两个标记很难合并 故应该标记永久化减少合并的麻烦。
这里我们很完美的解决了 二维线段树的问题。 单次操作时间显然是 logn^2.
二维线段树->树套树的更多相关文章
- poj 2155 matrix 二维线段树 线段树套线段树
题意 一个$n*n$矩阵,初始全为0,每次翻转一个子矩阵,然后单点查找 题解 任意一种能维护二维平面的数据结构都可以 我这里写的是二维线段树,因为四分树的写法复杂度可能会退化,因此考虑用树套树实现二维 ...
- BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)
题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...
- UVA 11297 线段树套线段树(二维线段树)
题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要 不同的处理方式,非叶子形成的 ...
- HDU 4819 Mosaic --二维线段树(树套树)
题意: 给一个矩阵,每次查询一个子矩阵内的最大最小值,然后更新子矩阵中心点为(Max+Min)/2. 解法: 由于是矩阵,且要求区间最大最小和更新单点,很容易想到二维的线段树,可是因为之前没写过二维的 ...
- HDU 1823 Luck and Love 二维线段树(树套树)
点击打开链接 Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)
[BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...
- poj 1195:Mobile phones(二维线段树,矩阵求和)
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 14391 Accepted: 6685 De ...
- HDU 4819 Mosaic(13年长春现场 二维线段树)
HDU 4819 Mosaic 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4819 题意:给定一个n*n的矩阵,每次给定一个子矩阵区域(x,y,l) ...
- 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)
题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...
随机推荐
- MySQL 索引结构 hash 有序数组
MySQL 索引结构 hash 有序数组 除了最常见的树形索引结构,Hash索引也有它的独到之处. Hash算法 Hash本身是一种函数,又被称为散列函数. 它的思路很简单:将key放在数组里,用 ...
- YAML & JSON &XML如何选择
前言 本文翻译https://www.csestack.org/yaml-vs-json-vs-xml-difference/,下文会针对当前现有的数据序列化语言做下梳理.重点突出YAML是什么,优缺 ...
- 【盗版动归】Codeforces998C——Convert to Ones 归一操作
嘤嘤嘤,因为最近文化课老师追的紧了+班主任开班会,所以这博客是赶制的赝品 题目: You've got a string a1,a2,…,ana1,a2,…,an, consisting of zer ...
- 线下---复习day02
目录 1 后续课程安排 2 作业讲解 3 python中的魔法方法 setattr,getattr,setitem,getitem演示 with 上下文管理器 eq 4 cookie,session, ...
- web 基础(二) HTML5
web 基础(二) HTML5 一.HTML5 HTML5 是最新的 HTML 标准.是专门为承载丰富的 web 内容而设计的,并且无需额外插件.它拥有新的语义.图形以及多媒体元素.并提供的新元素和新 ...
- 浅析Python垃圾回收机制!
Python垃圾回收机制 目录 Python垃圾回收机制 1. 内存泄露 2. Python什么时候启动垃圾回收机制? 2.1 计数引用 2.2 循环引用 问题:引用计数是0是启动垃圾回收的充要条件吗 ...
- redis(一):Redis 数据类型
Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...
- Django- 开发通用且万能的的权限框架组件
本节内容 需求讨论 权限设计 代码设计 自定义权限钩子 业务场景分析 假设我们在开发一个培训机构的 客户关系管理系统,系统分客户管理.学员管理.教学管理3个大模块,每个模块大体功能如下 客户管理销售人 ...
- 没想到 Google 排名第一的编程语言,为什么会这么火?
没想到吧,Python 又拿第一了! 在 Google 公布的编程语言流行指数中,Python 依旧是全球范围内最受欢迎的技术语言! 01 为什么 Python 会这么火? 核心还是因为企业需要用 ...
- canvas学习01
canvas 必须指定宽高,确定可绘图区域的大小 canvas标签里写的是浏览器不支持canvas时展示的内容 <canvas id="drawing" width=&quo ...