P3437 [POI2006]TET-Tetris 3D
题目描述
The authors of the game "Tetris" have decided to make a new, three-dimensional version, in which cuboids would fall down on a rectangular platform. The blocks fall down separately in a certain order, just like in the two-dimensional game. A block falls down until it reaches an obstacle: the platform or another block, that has already stopped - then it stops and remains in this exact position till the game is over.
However, the authors wanted to change the spirit of the game, turning it from a simple arcade-game into a play far more puzzling. Knowing the order of the falling blocks and their flight path the player's task is to tell the height of the highest point of the arrangement after all blocks have fallen down (and stopped). All the blocks are falling down vertically and do not rotate while falling. For convenience we'll introduce a cartesian coordinate system on the platform, with the center in one of the platform's corners and the axes parallel to the platform's edges.
Write a programme that automates verification of the player's answer.
TaskWrite a programme that:
reads the descriptions of subsequent falling blocks from the standard input,determines the height of the highest point of the arrangement of blocks after all have fallen down and stopped,writes the result to the standard output.
给定一个矩阵,初始每个位置上的元素都是0,每次选择一个子矩形,将这个子矩形内的值修改为这个子矩形内的最大值+h,求最终所有位置上的最大值
输入输出格式
输入格式:
In the first line of the input there are three integers DD, SS and NN (1le Nle 20 0001≤N≤20 000, 1le D,Sle 1 0001≤D,S≤1 000), separated by single spaces and denoting respectively: the length and the depth of the platform and the number of blocks that are going to fall down on it. In the following NN lines the descriptions of subsequent blocks are given, one in each line.
Each description of a block consists of five integers: dd,ss,ww,xx and yy (1le d1≤d, 0le x0≤x, d+xle Dd+x≤D, 1le s1≤s, 0le y0≤y, s+yle Ss+y≤S, 1le wle 100 0001≤w≤100 000), representing a block of length dd depth ss and height ww. This very block will be be falling down on the platform with its d imes sd×s face as the bottom, where the length and depth of the block are parallel to those of the platform. The coordinates of the vertices of the projection of the block on the platform are: (x,y)(x,y), (x+d,y)(x+d,y), (x,y+s)(x,y+s) and (x+d,y+s)(x+d,y+s).
第一行输入D,S,N,就是长宽和操作数
后面每行读入5个数,d,s,h,x,y,表示把
(x,y),(x+d-1,y),(x,y+s-1),(x+d-1,y+s-1)为四顶点的子矩阵进行操作
h就是题目描述里的h
注意行列是从0开始数的
输出格式:
The first and only line of the standard output should contain exactly one integer, the height of the highest point of the arrangement of blocks after all have fallen down and stopped.
注意到这个矩形修改矩形查询最大值的所有位置上的值是非减的,否则我们没法使用二维线段树配合标记永久化完成。
先考虑一维的情况,区间求最大值,区间赋值最大值加上某个正数
在线段树中维护一个(mx)和一个(tag),分别表示区间最大值和修改后的值
对于修改操作,对路径上的每一个节点都用待修改的值尝试更新(mx)数组,因为这个节点一定包含这个小区间,所以可以更新
但(tag)操作只有区间完全被覆盖时才更新,不下传一直呆在这个区间
对于查询操作,对路径上的每一个节点都尝试使用(tag)数组更新答案,因为tag是对整个区间打的,所以子区间可以直接使用
在区间完全被覆盖的情况下,我们才可以用(mx)数组更新答案
这就是所谓的标记永久化
为什么要这样,因为第二维的树是没法使用子节点快速更新答案的,也不好下传
再考虑第二维的情况,第二维的线段树每一个节点都放着两颗颗第一维线段树
一颗代表(mx)树,一颗代表(tag)树
然后剩下的就和第一维的情况非常相似了
Code:
#include <cstdio>
const int N=2050;
int n,m;
int max(int x,int y){return x>y?x:y;}
#define ls id<<1
#define rs id<<1|1
struct segy
{
int mx[N],tag[N];
void change(int id,int l,int r,int L,int R,int val)
{
mx[id]=max(mx[id],val);
if(l==L&&r==R)
{
tag[id]=max(tag[id],val);
return;
}
int Mid=L+R>>1;
if(r<=Mid) change(ls,l,r,L,Mid,val);
else if(l>Mid) change(rs,l,r,Mid+1,R,val);
else change(ls,l,Mid,L,Mid,val),change(rs,Mid+1,r,Mid+1,R,val);
}
int query(int id,int l,int r,int L,int R)
{
if(l==L&&r==R)
return mx[id];
int ans=tag[id],Mid=L+R>>1;
if(r<=Mid) ans=max(ans,query(ls,l,r,L,Mid));
else if(l>Mid) ans=max(ans,query(rs,l,r,Mid+1,R));
else ans=max(ans,max(query(ls,l,Mid,L,Mid),query(rs,Mid+1,r,Mid+1,R)));
return ans;
}
};
struct segx
{
segy mx[N],tag[N];
void change(int id,int l,int r,int L,int R,int ll,int rr,int val)
{
mx[id].change(1,ll,rr,1,m,val);
if(l==L&&r==R)
{
tag[id].change(1,ll,rr,1,m,val);
return;
}
int Mid=L+R>>1;
if(r<=Mid) change(ls,l,r,L,Mid,ll,rr,val);
else if(l>Mid) change(rs,l,r,Mid+1,R,ll,rr,val);
else change(ls,l,Mid,L,Mid,ll,rr,val),change(rs,Mid+1,r,Mid+1,R,ll,rr,val);
}
int query(int id,int l,int r,int L,int R,int ll,int rr)
{
if(l==L&&r==R)
return mx[id].query(1,ll,rr,1,m);
int ans=tag[id].query(1,ll,rr,1,m),Mid=L+R>>1;
if(r<=Mid) ans=max(ans,query(ls,l,r,L,Mid,ll,rr));
else if(l>Mid) ans=max(ans,query(rs,l,r,Mid+1,R,ll,rr));
else ans=max(ans,max(query(ls,l,Mid,L,Mid,ll,rr),query(rs,Mid+1,r,Mid+1,R,ll,rr)));
return ans;
}
}t;
int main()
{
int d,s,h,x,y,k;
scanf("%d%d%d",&n,&m,&k);
while(k--)
{
scanf("%d%d%d%d%d",&d,&s,&h,&x,&y),++x,++y;
t.change(1,x,x+d-1,1,n,y,y+s-1,t.query(1,x,x+d-1,1,n,y,y+s-1)+h);
}
printf("%d
",t.query(1,1,n,1,n,1,m));
return 0;
}
2018.9.4