现在上真正的二维线段树 毕竟 刚刚那个是卡常 过题我们现在做一个更高级的做法二维线段树。

大体上维护一颗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.

二维线段树->树套树的更多相关文章

  1. poj 2155 matrix 二维线段树 线段树套线段树

    题意 一个$n*n$矩阵,初始全为0,每次翻转一个子矩阵,然后单点查找 题解 任意一种能维护二维平面的数据结构都可以 我这里写的是二维线段树,因为四分树的写法复杂度可能会退化,因此考虑用树套树实现二维 ...

  2. 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[ ...

  3. UVA 11297 线段树套线段树(二维线段树)

    题目大意: 就是在二维的空间内进行单个的修改,或者进行整块矩形区域的最大最小值查询 二维线段树树,要注意的是第一维上不是叶子形成的第二维线段树和叶子形成的第二维线段树要  不同的处理方式,非叶子形成的 ...

  4. HDU 4819 Mosaic --二维线段树(树套树)

    题意: 给一个矩阵,每次查询一个子矩阵内的最大最小值,然后更新子矩阵中心点为(Max+Min)/2. 解法: 由于是矩阵,且要求区间最大最小和更新单点,很容易想到二维的线段树,可是因为之前没写过二维的 ...

  5. HDU 1823 Luck and Love 二维线段树(树套树)

    点击打开链接 Luck and Love Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  6. 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)

    [BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...

  7. poj 1195:Mobile phones(二维线段树,矩阵求和)

    Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14391   Accepted: 6685 De ...

  8. HDU 4819 Mosaic(13年长春现场 二维线段树)

    HDU 4819 Mosaic 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4819 题意:给定一个n*n的矩阵,每次给定一个子矩阵区域(x,y,l) ...

  9. 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)

    题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...

随机推荐

  1. 带你学够浪:Go语言基础系列 - 10分钟学方法和接口

    文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 对于一般的语言使用者来说 ,20% 的语言特性就能够满 ...

  2. CF796C Bank Hacking 题解

    洛谷链接 题目 Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To ...

  3. 链表中倒数第k个节点(剑指offer-14)

    /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ ...

  4. VSCode 配 uni-app

    CLI工程 全局安装vue-cli npm install -g @vue/cli 通过cli创建uni-app项目 vue create -p dcloudio/uni-preset-vue uni ...

  5. java IO流 (二) IO流概述

    1.流的分类* 1.操作数据单位:字节流.字符流* 2.数据的流向:输入流.输出流* 3.流的角色:节点流.处理流 图示: 2.流的体系结构 说明:红框对应的是IO流中的4个抽象基类.蓝框的流需要大家 ...

  6. LeetCode第4题:寻找两个有序数组的中位数

    double Solution::findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) ...

  7. ES6的功能简介

    1. let, const, var let: 块级作用域, 不存在变量提升, 值可更改 const:块级作用域, 不能存在变量提升, 值不可更改 var: 函数级作用域, 变量提升, 值可更改 案例 ...

  8. Tips1:考虑用静态工厂方法代替构造器

    用静态工厂方法来代替构造器为外界提供对象 描述: 静态工厂方法代替构造器来给外界提供对象,创建对象依然是由构造器来完成的 创建对象和提供对象: 创建对象的方式: 构造器 提供对象来哦方式: 构造器 类 ...

  9. JavaScript动画实例:旋转的正三角形

    给定一个正三角形的重心坐标为(x0,y0),高为h,可以用如下的语句绘制一个底边水平的正三角形. ctx.beginPath(); ctx.moveTo(x0,y0-h*2/3); ctx.lineT ...

  10. Burp Suite Intruder Module - 攻击模块

    参考链接:https://portswigger.net/burp/documentation/desktop/tools/intruder/using 主要思路:在Intruder模块下设定Targ ...