BZOJ4364 [IOI2014]wall砖墙

题目描述:

健佳正在用大小相同的砖块来砌起一面墙。这面墙由 列砖块所组成,它们从左到右的编号0至n-1。各列的高度可
以不同。各列的高度就是该列砖块的数量。健佳用如下方式来建造这面墙。最开始每列都没有砖块。此后,健佳
通过k个阶段的增加(adding)或移除(removing)砖块操作来砌墙。当所有k个阶段完成后,这面墙就砌好了。在每
个阶段中,健佳都会被告知一个连续的砖块列的范围,以及一个高度值h,然后他就完成如下过程:在增加砖块
(adding)阶段,对于给定的列范围中高度小于h的列,健佳会增加砖块使它们的高度都恰好等于h。此时他不会改
变那些高度大于或等于h的列。在移除砖块(removing)阶段,对于给定的列范围中高度大于 的列,健佳会移除砖
块使它们的高度都恰好等于h。此时他不会改变那些高度小于或等于h的列。你的任务就是计算出这面墙的最后形
状。
 
题解:
线段树。

考虑如何处理两个标记之间的覆盖。 首先,如果一个结点即将被打上一个down标记,值为x,并且同时它的up标记为y,那么分情况讨论。

1.如果x<y: 直接打上,无影响,因为这个区间内的值都将被修改成x~y这个范围内的值。

2.如果x>y: 此时不难看出,有了之前的up标记,这个区间内的值应该全部都大于等于y。此时再进行一个down操作,则会把这个区间内的值全部改为x。因此把up标记改为x然后打上down标记。

打up标记也是同理。

最后遍历一次就行了。

附上代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,k,minn[8000001],maxx[8000001];
void pushup(int k)
{
    minn[k]=min(minn[k<<1],minn[k<<1|1]);
    maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}
void pushdown(int k)
{
    if(minn[k]>maxx[k<<1])
    {
        maxx[k<<1]=minn[k];
        minn[k<<1]=minn[k];
    }
    else if(minn[k]>minn[k<<1])
        minn[k<<1]=minn[k];
    if(minn[k]>maxx[k<<1|1])
    {
        maxx[k<<1|1]=minn[k];
        minn[k<<1|1]=minn[k];
    }
    else if(minn[k]>minn[k<<1|1])
        minn[k<<1|1]=minn[k];
    if(maxx[k]<minn[k<<1])
    {
        maxx[k<<1]=maxx[k];
        minn[k<<1]=maxx[k];
    }
    else if(maxx[k]<maxx[k<<1])
        maxx[k<<1]=maxx[k];
    if(maxx[k]<minn[k<<1|1])
    {
        maxx[k<<1|1]=maxx[k];
        minn[k<<1|1]=maxx[k];
    }
    else if(maxx[k]<maxx[k<<1|1])
        maxx[k<<1|1]=maxx[k];
}
void update1(int l,int r,int x,int y,int h,int k)
{
    if(x<=l&&r<=y)
    {
        minn[k]=max(minn[k],h);
        maxx[k]=max(maxx[k],h);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(k);
    if(mid>=x)
        update1(l,mid,x,y,h,k<<1);
    if(mid<y)
        update1(mid+1,r,x,y,h,k<<1|1);
    pushup(k);
}
void update2(int l,int r,int x,int y,int h,int k)
{
    if(x<=l&&r<=y)
    {
        minn[k]=min(minn[k],h);
        maxx[k]=min(maxx[k],h);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(k);
    if(mid>=x)
        update2(l,mid,x,y,h,k<<1);
    if(mid<y)
        update2(mid+1,r,x,y,h,k<<1|1);
    pushup(k);
}
void query(int l,int r,int k)
{
    if(l==r)
    {
        printf("%d\n",minn[k]);
        return;
    }
    int mid=(l+r)>>1;
    pushdown(k);
    query(l,mid,k<<1);
    query(mid+1,r,k<<1|1);
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++)
    {
        int k,x,y,z;
        scanf("%d%d%d%d",&k,&x,&y,&z);
        if(k==1)
        {
            update1(1,n,x+1,y+1,z,1);
        }
        else
        {
            update2(1,n,x+1,y+1,z,1);
        }
    }
    query(1,n,1);
}

 

posted @ 2018-10-24 18:56  jiangminghong  阅读(186)  评论(0编辑  收藏  举报