【POI2006】【BZOJ1513】Tet-Tetris 3D

Description

Task: Tetris 3D “Tetris” 游戏的作者决定做一个新的游戏, 一个三维的版本, 在里面很多立方体落在平面板,一个立方体开始落下直到碰上一个以前落下的立方体或者落地即停止. 作者想改变一下游戏的目的使得它更大众化,在新游戏中你将知道落下的立方体信息以及位置,你的任务就是回答所有立方体落下后最高的方块的高度.所有的立方体在下落过程中都是垂直的并且不会旋转.平板左下角坐标为原点,并且平行于坐标轴.
Input

第一行给出三个整数 D, S and N ( 1<= N<= 20 000, 1<= D, S <=1 000), 分别表示平板的长和宽以及下落立方体的数目. 接下来N 行每行描述一个立方体. 每行包含5个整数: d, s, w, x and y (1<= d, 0 <=x, d + x<= D, 1 <=s, 0<= y, s + y<= S, 1<= w <=100 000), 分别表示立方体的长\宽\高以及落下的左下角坐标, 长和宽都是平行于平板坐标轴的,落下后立方体着地的四个角坐标分别为: (x, y), (x + d, y), (x, y + s) and (x + d, y + s).
Output

一个整数表示所有立方体落下后最高的方块的高度.
Sample Input

7 5 4

4 3 2 0 0

3 3 1 3 0

7 1 2 0 3

2 3 3 2 2

Sample Output

6

HINT

Source

这好像是我写的第一个二维线段树的题

二维线段树+标记永久化

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 1010
#define ln rt<<1
#define rn rt<<1|1
#define GET (ch>='0'&&ch<='9')
using namespace std;
int D,S,N;
int ql,qr,qd,qu;
void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
struct seg
{
    int maxn[MAXN*3],flag[MAXN*3];
    void modify(int rt,int L,int R,int l,int r,int delta)
    {
        maxn[rt]=max(maxn[rt],delta);int mid=(L+R)>>1;
        if (l==L&&r==R) {flag[rt]=max(flag[rt],delta);return;}
        if (l>mid)   modify(rn,mid+1,R,l,r,delta);
        else    if (r<=mid)  modify(ln,L,mid,l,r,delta);
        else    modify(ln,L,mid,l,mid,delta),modify(rn,mid+1,R,mid+1,r,delta);
    }
    int query(int rt,int L,int R,int l,int r)
    {
        if (l==L&&r==R) return maxn[rt];
        int mid=(L+R)>>1,ret=flag[rt];
        if (l>mid)   ret=max(ret,query(rn,mid+1,R,l,r));
        else    if (r<=mid)  ret=max(ret,query(ln,L,mid,l,r));
        else    ret=max(ret,max(query(ln,L,mid,l,mid),query(rn,mid+1,R,mid+1,r)));
        return ret;
    }
};
struct Seg
{
    seg tree[MAXN*3],flag[MAXN*3];
    void modify(int rt,int L,int R,int l,int r,int delta)
    {
        tree[rt].modify(1,1,S,qd,qu,delta);int mid=(L+R)>>1;
        if (l==L&&r==R) {flag[rt].modify(1,1,S,qd,qu,delta);return;}
        if (l>mid)   modify(rn,mid+1,R,l,r,delta);
        else    if (r<=mid)  modify(ln,L,mid,l,r,delta);
        else    modify(ln,L,mid,l,mid,delta),modify(rn,mid+1,R,mid+1,r,delta);
    }
    int query(int rt,int L,int R,int l,int r)
    {
        if (L==l&&r==R) return tree[rt].query(1,1,S,qd,qu);
        int mid=(L+R)>>1,ret=flag[rt].query(1,1,S,qd,qu);
        if (l>mid)   ret=max(ret,query(rn,mid+1,R,l,r));
        else    if (r<=mid)  ret=max(ret,query(ln,L,mid,l,r));
        else    ret=max(ret,max(query(ln,L,mid,l,mid),query(rn,mid+1,R,mid+1,r)));
        return ret;
    }
}Tree;
int main()
{
    in(D);in(S);in(N);int d,s,w,x,y;
    while (N--)
    {
        in(d);in(s);in(w);in(x);in(y);ql=x+1;qr=x+d;qd=y+1;qu=y+s;
        int ans=Tree.query(1,1,D,ql,qr);
        Tree.modify(1,1,D,ql,qr,ans+w);
    }
    ql=1;qr=D;qd=1;qu=S;
    printf("%d\n",Tree.query(1,1,D,1,D));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值