BZOJ 1513 [POI2006]Tet-Tetris 3D 二维线段树

来源:互联网 发布:康美包员工 知乎 编辑:程序博客网 时间:2024/05/17 08:28

题意:
d*s的平面上,掉落n个方块。
每个方块会掉落在地上或者另一个方块上。
现给定每个方块的长宽高以及掉落位置。
求解最后能摞多高
(牛顿死的早)
解析:
显然h[i]=max(h[j])+w[i] (j小于i&&i可以落在j上)。
如何维护这个式子呢,对于这种数据范围,我们直接上一个二维数据结构维护平面内最大值即可。
但是需要注意的是,二维线段树并不可以标记下传。
所以我们不妨考虑标记永久化,查询某个区间的时候,把根节点到他路径上所有的点的最大值再取一个最大即可。
所以我们需要维护两个东西,第一个是根节点到该节点的最大值,第二个就是该节点的确切值。
代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1100#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;int d,s,n,ans;struct SegTreeY{    int tree[3005],col[3005];    void update(int L,int R,int l,int r,int rt,int val)    {        tree[rt]=max(tree[rt],val);        if(L<=l&&r<=R)        {            col[rt]=max(col[rt],val);            return ;        }        int mid=(l+r)>>1;        if(R<=mid)update(L,R,lson,val);        else if(L>mid)update(L,R,rson,val);        else        {            update(L,mid,lson,val);            update(mid+1,R,rson,val);        }    }    int query(int L,int R,int l,int r,int rt)    {        if(L<=l&&r<=R)        {            return tree[rt];        }        int mid=(l+r)>>1,re=col[rt];        if(R<=mid)re=max(re,query(L,R,lson));        else if(L>mid)re=max(re,query(L,R,rson));        else        {            re=max(re,query(L,mid,lson));            re=max(re,query(mid+1,R,rson));        }        return re;    }};struct SegTreeX{    SegTreeY tree[3005],col[3005];    void update(int L,int R,int l,int r,int rt,int y1,int y2,int val)    {        tree[rt].update(y1,y2,1,s,1,val);        if(L<=l&&r<=R)        {            col[rt].update(y1,y2,1,s,1,val);            return;        }        int mid=(l+r)>>1;        if(R<=mid)update(L,R,lson,y1,y2,val);        else if(L>mid)update(L,R,rson,y1,y2,val);        else        {            update(L,mid,lson,y1,y2,val);            update(mid+1,R,rson,y1,y2,val);        }    }    int query(int L,int R,int l,int r,int rt,int y1,int y2)    {        if(L<=l&&r<=R)        {            return tree[rt].query(y1,y2,1,s,1);        }        int mid=(l+r)>>1,re=col[rt].query(y1,y2,1,s,1);        if(R<=mid)re=max(re,query(L,R,lson,y1,y2));        else if(L>mid)re=max(re,query(L,R,rson,y1,y2));        else        {            re=max(re,query(L,mid,lson,y1,y2));            re=max(re,query(mid+1,R,rson,y1,y2));        }        return re;    }}TREE;int main(){    #ifndef ONLINE_JUDGE        freopen("1513.in","r",stdin);        freopen("1513.out","w",stdout);    #endif        scanf("%d%d%d",&d,&s,&n);        d++,s++;        for(int i=1;i<=n;i++)        {            int d1,s1,h1,x1,y1;            scanf("%d%d%d%d%d",&d1,&s1,&h1,&x1,&y1);            x1++,y1++;            int x2=x1+d1-1,y2=y1+s1-1;            int ma=TREE.query(x1,x2,1,d,1,y1,y2);            ans=max(ans,ma+h1);            ma+=h1;            TREE.update(x1,x2,1,d,1,y1,y2,ma);        }        printf("%d\n",ans);    #ifndef ONLINE_JUDGE        fclose(stdin);fclose(stdout);    #endif    return 0;}
0 0
原创粉丝点击