树套树+标记永久化:[POI 2006] TET-Tetris 3D&&SPOJ1741 TETRIS3D - Tetris 3D题解

双倍经验!

非常经典的题目。

思路

省流:线段树套线段树、标记永久化。

落下一个方块时,我们需要求出该方块在地面投影的区域中,最高的方块高度 x x x,然后将该区域的高度统一更改为 x + w x+w x+w。

即:动态维护二维平面赋值、求二维平面的最大值。

这样一来,就不能用树状数组套线段树了,只能用线段树套线段树。

不过,正常的线段树套线段树是无法维护的,这时就有一个神奇的操作------标记永久化。我们先考虑一维的线段树,进行区间操作时,要维护区间最大值 m x mx mx 与懒标记 t a g tag tag,实时 push_down 和 push_up。我们现在要做的就是规避掉 push_down 和 push_up。对于 push_up,由于本题中的高度只增不降,所以修改时,我们直接用 x + w x+w x+w 去尝试更新修改路径上的每一个 m x mx mx。对于 push_down,我们直接不干了!这样一来,在求区间 max ⁡ \max max 的时候,我们需要对查询路径上的每一个 t a g tag tag 都取 max ⁡ \max max(修改操作只增不降,所以 max ⁡ \max max 一定是最新的操作),对于区间完全被覆盖的,我们还需要用答案对 m x mx mx 取 max ⁡ \max max。

二维线段树也是一样的,对于外层线段树上的每个节点,我们都需要开两棵树,一棵 m x mx mx,一棵 t a g tag tag。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int d,s,n,rt[4005],rtt[4005];
#define mid ((l+r)>>1)
struct js
{
	int tr[2000005],tag[2000005],cnt=0,ls[2000005],rs[2000005];
	void push_down(int p)
	{
		if(!ls[p]) ls[p]=++cnt;
		if(!rs[p]) rs[p]=++cnt;
		tag[ls[p]]=max(tag[ls[p]],tag[p]),tr[ls[p]]=max(tr[ls[p]],tag[p]);
	 	tag[rs[p]]=max(tag[rs[p]],tag[p]),tr[rs[p]]=max(tr[rs[p]],tag[p]);
		tag[p]=0;
	}
	void push_up(int p)
	{
		tr[p]=max(tr[ls[p]],tr[rs[p]]);
	}
	void update(int &p,int l,int r,int L,int R,int w)
	{
		if(!p) p=++cnt;
		if(L<=l&&R>=r)
		{
			tr[p]=max(tr[p],w),tag[p]=max(tag[p],w);
			return ;
		}
		push_down(p);
		if(L<=mid&&!ls[p]) ls[p]=++cnt;
		if(R>mid&&!rs[p]) rs[p]=++cnt;
		if(L<=mid) update(ls[p],l,mid,L,R,w);
		if(R>mid) update(rs[p],mid+1,r,L,R,w);
		push_up(p); 
	}
	int query(int p,int l,int r,int L,int R)
	{
		if(!p) return 0;
		if(L<=l&&R>=r) return tr[p];
		int res=0;
		push_down(p);
		if(L<=mid) res=max(res,query(ls[p],l,mid,L,R));
		if(R>mid) res=max(res,query(rs[p],mid+1,r,L,R));
		return res;
	}
}tr,trr;
//tr是mx,trr是tag 
void update(int p,int l,int r,int L,int R,int ll,int rr,int w)
{
	tr.update(rt[p],1,s,ll,rr,w);
	if(L<=l&&R>=r)
	{
		trr.update(rtt[p],1,s,ll,rr,w);
		return ;
	}
	if(L<=mid) update(p<<1,l,mid,L,R,ll,rr,w);
	if(R>mid) update((p<<1)|1,mid+1,r,L,R,ll,rr,w);
}
int query(int p,int l,int r,int L,int R,int ll,int rr)
{
	int res=0;
	res=trr.query(rtt[p],1,s,ll,rr);
	if(L<=l&&R>=r)
	{
		res=max(res,tr.query(rt[p],1,s,ll,rr));
		return res;
	}
	if(L<=mid) res=max(res,query(p<<1,l,mid,L,R,ll,rr));
	if(R>mid) res=max(res,query((p<<1)|1,mid+1,r,L,R,ll,rr));
	return res;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>d>>s>>n;
	while(n--)
	{
		int dd,ss,w,x,y;
		cin>>dd>>ss>>w>>x>>y;
		x++,y++,update(1,1,d,x,x+dd-1,y,y+ss-1,w+query(1,1,d,x,x+dd-1,y,y+ss-1)); 
	}
	cout<<query(1,1,d,1,d,1,s);
	return 0;
} 
相关推荐
Titan20247 分钟前
HTTPS基础知识梳理
服务器·网络·c++·网络协议·学习·http·https
艾莉丝努力练剑9 分钟前
【AI大模型接入SDK】SSE协议
c++·学习·面试·大模型·sdk
方方洛11 分钟前
vllm教程-03-架构设计
算法·架构
玄昌盛不会编程13 分钟前
LeetCode——2091. 从数组中移除最大值和最小值
java·算法·leetcode
如何取名25 分钟前
结合实际业务进行LRU淘汰算法优化设计(数据库开发日志)
数据库·算法
郝学胜_神的一滴27 分钟前
C++11 工程级应用 06:自己造一个类似Python的Range迭代器
c++·后端
aichitang202429 分钟前
快乐泛函每一天:希尔伯特空间中的最佳逼近与正交投影定理
人工智能·考研·算法·ai·面试·泛函分析
淬炼之火34 分钟前
笔记:Visually-Guided Policy Optimization for Multimodal Reasoning
人工智能·笔记·算法·机器学习·语言模型·自然语言处理
一只QAQ36 分钟前
c++项目
java·c++·算法
学习星球40 分钟前
空天地一体化网络(NTN)深度解析:从Starlink D2C到3GPP NTN,卫星直连手机是如何实现的?
网络·人工智能·算法·智能手机·php