• 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
    ",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);
    }
  • 相关阅读:
    DFS复习
    二叉搜索树专题
    二叉树路径问题
    二叉树LCA--leetcode236题
    二叉树创建与前、中、后序遍历
    leetCode--n数之和--哈希表/双指针
    leetCode--单词接龙--BFS
    vue-router简单实现
    Promise的简单实现
    闭包&作用域链&let
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/9845453.html
Copyright © 2020-2023  润新知