题目链接

下落一个d*s的方块,则要在这个平面区域找一个最高的h'

更新整个平面区域的值为h+h'

对于本题,维护最大高度h和all

对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵线段树t2(h和all)

(同一维,需要维护独立的两棵线段树)

t1要用标记永久化实现,t2普通和标记永久化都可以

空间O(n^2) 时间O(n*(logn)^2)

**标记永久化: **

对于树套树(二维线段树)来说,标记下传(PushDown)与信息上传(PushUp)就很难实现了

这时用到标记永久化

写普通线段树时,对修改区间打标记,在需要的时候下放标记并更新

那可不可以不对标记进行下放,而是经过的时候统计标记对答案的贡献,从而省去标记下放过程?

以区间加、求和为例,新线段树每个节点维护sum,all,分别表示该节点包含区间的和,与该节点包含的整个区间都有的标记all

更新时,一路更新经过节点的sum值,直到当前节点区间完全被目标区间覆盖,更新该节点的all,return (顺序修改就省去了PushUp)

查询时 正相反,一路统计经过节点的all值,直到当前节点区间完全被目标区间覆盖,用该节点的sum更新答案

优化前:

/*
6564ms 123972KB
注:本题矩形高度只会越来越高,所以信息上传时不需要用到左右儿子的信息,使用标记永久化就不会有问题
若答案并不是单调的,那么更新答案时就会出现问题,因为并不知道标记打上的顺序是谁在前谁在后
而且必须要取最大值,不能直接覆盖
不太明白...
注意是从0开始 不要写错!
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
//#define gc() (SS==TT &&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define lson node[rt].ls,l,m
#define rson node[rt].rs,m+1,r
const int N=1e3+2,MAXIN=5e6; int r,c;
//char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
struct Seg_Tree
{
int tot;
struct Node
{
int ls,rs,maxh,all;
}node[N<<1];
void Build(int l,int r)
{
int p=tot++;
node[p].maxh=node[p].all=0;
if(l==r) {node[p].ls=node[p].rs=-1; return;}
int m=l+r>>1;
node[p].ls=tot, Build(l,m);
node[p].rs=tot, Build(m+1,r);
}
void Init(int l,int r)
{
tot=0, Build(l,r);
}
void Modify(int rt,int l,int r,int L,int R,int v)
{
// node[rt].maxh=v;
node[rt].maxh=std::max(node[rt].maxh,v);
if(L<=l && r<=R)
{
node[rt].all=std::max(node[rt].all,v);
return;
}
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
}
int Query(int rt,int l,int r,int L,int R)
{
if(L<=l && r<=R) return node[rt].maxh;
int res=node[rt].all,m=l+r>>1;
if(L<=m) res=std::max(res,Query(lson,L,R));
if(m<R) res=std::max(res,Query(rson,L,R));
return res;
}
};
struct Seg_Tree2D
{
int tot;
struct Node
{
int ls,rs;
Seg_Tree maxh,all;
}node[N<<1];
void Build(int l,int r,int c)
{
int p=tot++;
node[p].all.Init(0,c), node[p].maxh.Init(0,c);
// node[p].l=l, node[p].r=r;
if(l==r) {node[p].ls=node[p].rs=-1; return;}
int m=l+r>>1;
node[p].ls=tot, Build(l,m,c);
node[p].rs=tot, Build(m+1,r,c);
}
void Init(int l,int r,int c)
{
tot=0, Build(l,r,c);
}
void Modify(int rt,int l,int r,int x1,int x2,int y1,int y2,int v)
{
node[rt].maxh.Modify(0,0,c,y1,y2,v);
if(x1<=l && r<=x2)
{
node[rt].all.Modify(0,0,c,y1,y2,v);
return;
}
int m=l+r>>1;
if(x1<=m) Modify(lson,x1,x2,y1,y2,v);
if(m<x2) Modify(rson,x1,x2,y1,y2,v);
}
int Query(int rt,int l,int r,int x1,int x2,int y1,int y2)
{
if(x1<=l && r<=x2) return node[rt].maxh.Query(0,0,c,y1,y2);
int res=node[rt].all.Query(0,0,c,y1,y2),m=l+r>>1;
if(x1<=m) res=std::max(res,Query(lson,x1,x2,y1,y2));//不是(lson,x1,m)![x1,m]是查询区间
if(m<x2) res=std::max(res,Query(rson,x1,x2,y1,y2));
return res;
}
}t; int main()
{
#ifndef ONLINE_JUDGE
freopen("3437.in","r",stdin);
#endif r=read()-1,c=read()-1;
t.Init(0,r,c);
int m=read(),x,y,d,s,h,tmp,x2,y2;
while(m--)
{
d=read(),s=read(),h=read(),x=read(),y=read();
x2=x+d-1, y2=y+s-1;
tmp=t.Query(0,0,r,x,x2,y,y2);
t.Modify(0,0,r,x,x2,y,y2,h+tmp);
// printf("MAX:%d\n",t.Query(0,0,r,0,c));
}
printf("%d",t.Query(0,0,r,0,r,0,c)); return 0;
}

Optimize:

/*
3624ms 91035KB
初始为0的并不需要建树
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
//#define gc() getchar()
#define gc() (SS==TT &&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
const int N=1002*3,MAXIN=5e6; int n,m;
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
struct Seg_Tree
{
int maxh[N],all[N];
void Modify(int rt,int l,int r,int L,int R,int v)
{
maxh[rt]=std::max(maxh[rt],v);
if(L<=l && r<=R)
{
all[rt]=std::max(all[rt],v);
return;
}
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
}
int Query(int rt,int l,int r,int L,int R)
{
if(L<=l && r<=R) return maxh[rt];
int res=all[rt],m=l+r>>1;
if(L<=m) res=std::max(res,Query(lson,L,R));
if(m<R) res=std::max(res,Query(rson,L,R));
return res;
}
};
struct Seg_Tree2D
{
Seg_Tree maxh[N],all[N];
void Modify(int rt,int l,int r,int L,int R,int y1,int y2,int v)
{
maxh[rt].Modify(1,1,m,y1,y2,v);
if(L<=l && r<=R)
{
all[rt].Modify(1,1,m,y1,y2,v);
return;
}
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,y1,y2,v);
if(m<R) Modify(rson,L,R,y1,y2,v);
}
int Query(int rt,int l,int r,int L,int R,int y1,int y2)
{
if(L<=l && r<=R) return maxh[rt].Query(1,1,m,y1,y2);
int res=all[rt].Query(1,1,m,y1,y2),m=l+r>>1;
if(L<=m) res=std::max(res,Query(lson,L,R,y1,y2));//不是(lson,L,m)![L,m]是查询区间
if(m<R) res=std::max(res,Query(rson,L,R,y1,y2));
return res;
}
}t; int main()
{
#ifndef ONLINE_JUDGE
freopen("3437.in","r",stdin);
#endif n=read(),m=read();
int q=read(),x,y,d,s,h,tmp,x2,y2;
while(q--)
{
d=read(),s=read(),h=read(),x=read()+1,y=read()+1;
x2=x+d-1, y2=y+s-1;
tmp=t.Query(1,1,n,x,x2,y,y2);
t.Modify(1,1,n,x,x2,y,y2,h+tmp);
}
printf("%d",t.Query(1,1,n,1,n,1,m)); return 0;
}

洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)的更多相关文章

  1. 洛谷P3437 [POI2006]TET-Tetris 3D(二维线段树 标记永久化)

    题意 题目链接 Sol 二维线段树空间复杂度是多少啊qwqqq 为啥这题全网空间都是\(n^2\)还有人硬要说是\(nlog^2n\)呀.. 对于这题来说,因为有修改操作,我们需要在外层线段树上也打标 ...

  2. 【BZOJ1513】[POI2006]Tet-Tetris 3D 二维线段树

    [BZOJ1513][POI2006]Tet-Tetris 3D Description Task: Tetris 3D "Tetris" 游戏的作者决定做一个新的游戏, 一个三维 ...

  3. bzoj 1513 POI2006 Tet-Tetris 3D 二维线段树+标记永久化

    1511: [POI2006]OKR-Periods of Words Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 351  Solved: 220[S ...

  4. 洛谷 P1972 [SDOI2009]HH的项链-二维偏序+树状数组+读入挂(离线处理,思维,直接1~n一边插入一边查询),hahahahahahaha~

    P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含 ...

  5. 洛谷 P3438 - [POI2006]ZAB-Frogs(乱搞/李超线段树)

    题面传送门 首先一眼二分答案,我们假设距离 \((i,j)\) 最近的 scarefrog 离它的距离为 \(mn_{i,j}\),那么当我们二分到 \(mid\) 时我们显然只能经过 \(mn_{i ...

  6. 洛谷 P3688 - [ZJOI2017]树状数组(二维线段树+标记永久化)

    题面传送门 首先学过树状数组的应该都知道,将树状数组方向写反等价于前缀和 \(\to\) 后缀和,因此题目中伪代码的区间求和实质上是 \(sum[l-1...n]-sum[r...n]=sum[l-1 ...

  7. 洛谷 P5471 - [NOI2019] 弹跳(二维线段树优化建图+堆优化存边)

    题面传送门 一道非常有意思的题(大概可以这么形容?) 首先看到这类一个点想一个区域内连边的题目可以很自然地想到线段树优化建图,只不过这道题是二维的,因此需要使用二维线段树优化建图,具体来说,我们外层开 ...

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

  9. Codeforces 453E - Little Pony and Lord Tirek(二维线段树+ODT)

    Codeforces 题目传送门 & 洛谷题目传送门 一道难度 *3100 的 DS,而且被我自己搞出来了! 不过我终究还是技不如人,因为这是一个 \(n\log^2n\) + 大常数的辣鸡做 ...

随机推荐

  1. 【转】Python中的字符串与字符编码

    [转]Python中的字符串与字符编码 本节内容: 前言 相关概念 Python中的默认编码 Python2与Python3中对字符串的支持 字符编码转换 一.前言 Python中的字符编码是个老生常 ...

  2. 【转】Windows下安装python2和python3双版本

    [转]Windows下安装python2和python3双版本 现在大家常用的桌面操作系统有:Windows.Mac OS.ubuntu,其中Mac OS 和 ubuntu上都会自带python.这里 ...

  3. MySQL基于LVM快照的备份恢复(临时)

    目录1.数据库全备份2.准备LVM卷3.数据恢复到LVM卷4.基于LVM快照备份数据5.数据灾难恢复6.总结 写在前面:测试环境中已安装有mysql 5.5.36数据库,但数据目录没有存放在LVM卷, ...

  4. centos7和centos6.5环境rpm方式安装mysql5.7和mysql5.6详解

    centos环境安装mysql5.7 其实不建议安装mysql5.7 语法和配置可能和以前的版本区别较大,多坑,慎入 1.yum方式安装(不推荐) a.安装mysql5.7 yum源 centos6: ...

  5. centos6.5下系统编译定制iptables防火墙扩展layer7应用层访问控制功能及应用限制QQ2016上网

    iptables防火墙扩展之layer7应用层访问控制 概述: iptables防火墙是工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙.以基于网络层的数据包过滤机制为主,同 ...

  6. VeeValidate配置中文的两种方法

    使用VeeValidate时遇到的问题,下面是我找到的一些解决办法: VeeValidate一直报错早不到addlocale方法 解决办法:1.卸载掉当前版本,重新安装低版本如2.0.0-rc.25  ...

  7. ural1989 单点更新+字符串hash

    正解是双哈希,不过一次哈希也能解决.. 然后某个数字就对应一个字符串,虽然有些不同串对应同一个数字,但是概率非常小,可以忽略不计.从左到右.从右到左进行两次hash,如果是回文串,那么对应的整数必定存 ...

  8. 性能测试十九:jmeter参数优化+排错

    一:参数优化 1,控制台取样间隔的设置,在jmeter/bin/jmeter.properties文件中修改 summariser.interval=10,默认为30s,最低可修改为6s 2,Jvm参 ...

  9. 绝对定位后,position:absolute;不能使用margin: 0 auto;实现居中;

    声明: web小白的笔记,欢迎大神指点!联系QQ:1522025433. 我们都知道margin: 0 auto:可也实现块状元素的水平居中:但是对于绝对顶为的元素就会失效: 请看实例: <!d ...

  10. LICEcap方便快捷制作gif图片的工具

    总是看见别人的博客里面动态的小图片,是不是有种冲动自己也想搞,但是就是不知道咋搞,这里简单介绍一款很实用的制作gif的软件. LICEcap的网址:http://www.cockos.com/lice ...