zoukankan      html  css  js  c++  java
  • codeforces1198B Welfare State 线段树或单调栈+二分

    网址:http://codeforces.com/problemset/problem/1198/B

    题意:

    给出初始序列,规定两种操作:$1$ $p$ $x$代表把第$p$个值改成$x$,$2$ $x$代表把小于$x$的值都变成$x$,大于$x$的不变。求所有操作完成后的序列。($n ,m leq 2e5 $)。

    题解:

    一、线段树版本:

    操作即为典型的单点修改、区间修改和单点查询。lazy标记记录区间修改的值,由于$2$操作中大的$x$值一定会覆盖小的$x$值,故$lazy$标记下推时取较大值,单点修改时下推标记,由于单点修改是最高级的,所以每一次单点修改一定会清空目标叶节点的区间修改,然后单点查询时取$lazy$和叶节点值较大那个作为最终值。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define MAXN 200005
    #define ls (k<<1)
    #define rs (k<<1)+1
        
    const int MAXBUF = 1 << 20;
    char buf[1<<20], *fh=NULL, *ft=NULL;
    inline char gc() 
    {
        if(fh == ft) 
        {
            int l = fread(buf, 1, MAXBUF, stdin);
            ft = (fh = buf) + l;
        }
        return *fh++;
    }
        
    inline int read() 
    {
        int x = 0;
        char c = gc();
        for(; c < '0' || c > '9'; c = gc())
            ;
        for(; c >= '0' && c <= '9'; c = gc())
            x = (x << 3) + (x << 1) + c - '0';
        return x ;
    }
    inline void _write(long long x) 
    {
        if(x > 9)
            _write(x / 10);
        putchar(x % 10 + '0');
    }
    inline void write(long long x) 
    {
        _write(x);
        //putchar('
    ');
    }
        
    struct segtree
    {
        struct node
        {
            int l,r,val,lazy;
        };
        node tr[MAXN<<2];
        void build(int l,int r,int k)
        {
            tr[k].l=l,tr[k].r=r;
            tr[k].val=tr[k].lazy=0;
            if(l==r)
                return;
            int m=(l+r)>>1;
            build(l,m,ls);
            build(m+1,r,rs);
        }
        void down(int k)
        {
            tr[ls].lazy=max(tr[k].lazy,tr[ls].lazy);
            tr[rs].lazy=max(tr[k].lazy,tr[rs].lazy);
            tr[k].lazy=0;
        }
        void update1(int pos,int k,int val)
        {
            if(tr[k].l==tr[k].r)
            {
                tr[k].lazy=0;
                tr[k].val=val;
                return;
            }
            down(k);
            int m=(tr[k].l+tr[k].r)>>1;
            if(pos<=m)
                update1(pos,ls,val);
            else
                update1(pos,rs,val);
            tr[k].val=min(tr[ls].val,tr[rs].val);
        }
        void update2(int l,int r,int k,int val)
        {
            if(l<=tr[k].l&&tr[k].r>=tr[k].r)
            {
                tr[k].lazy=max(tr[k].lazy,val);
                return;
            }
            down(k);
            int m=(tr[k].l+tr[k].r)>>1;
            if(l<=m&&val>tr[ls].val)
                update2(l,r,ls,val);
            if(r>m&&val>tr[rs].val)
                update2(l,r,rs,val);
            tr[k].val=min(tr[ls].val,tr[rs].val);
        }
        int query(int pos,int k)
        {
            if(tr[k].l==tr[k].r)
                return max(tr[k].val,tr[k].lazy);
            down(k);
            int m=(tr[k].l+tr[k].r)>>1;
            if(pos<=m)
                return query(pos,ls);
            else
                return query(pos,rs);
        }
    };
    segtree tr;
    int main()
    {
        int n,m,a,p,x;
        //scanf("%d",&n);
        n=read();
        tr.build(1,n,1);
        for(int i=1;i<=n;++i)
        {
            a=read();
            tr.update1(i,1,a);
        }
        m=read();
        for(int i=0;i<m;++i)
        {
            a=read();
            p=read();
            if(a==1)
            {
                x=read();
                tr.update1(p,1,x);
            }
            else
                tr.update2(1,n,1,p);
        }
        for(int i=1;i<=n;++i)
        {
            write(tr.query(i,1));
            putchar((i==n?'
    ':' '));
        }
        return 0;
    }
    

     二、单调栈+二分解法:

    使用单调递减栈记录区间修改操作,然后对于每一个元素,单点修改直接在原数组中修改,记录最后一次修改时间,然后在栈中二分查找它的最后一次单点修改的时间的后面最大的一个区间修改(就是其后面第一个区间修改),然后两个取最大值。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=200005;
    int sta[MAXN],top=0,num[MAXN],lstch[MAXN],add[MAXN];
    
    const int MAXBUF = 1 << 20;
    char buf[1<<20], *fh=NULL, *ft=NULL;
    inline char gc() 
    {
        if(fh == ft) 
        {
            int l = fread(buf, 1, MAXBUF, stdin);
            ft = (fh = buf) + l;
        }
        return *fh++;
    }
        
    inline void read(int &x) 
    {
        x = 0; 
        char c = gc();
        for(; c < '0' || c > '9'; c = gc())
            ;
        for(; c >= '0' && c <= '9'; c = gc())
            x = (x << 3) + (x << 1) + c - '0';
        return;
    }
    inline void _write(long long x) 
    {
        if(x > 9)
            _write(x / 10);
        putchar(x % 10 + '0');
    }
    inline void write(long long x) 
    {
        _write(x);
        //putchar('
    ');
    }
    
    int main()
    {
        int n,m,a,p,x;
        //scanf("%d",&n);
        read(n);
        for(int i=1;i<=n;++i)
            read(num[i]);
            //scanf("%d",&num[i]);
        //scanf("%d",&m);
        read(m);
        for(int i=1;i<=m;++i)
        {
            read(a);
            //scanf("%d",&a);
            read(p);
            //scanf("%d",&p);
            if(a==1)
            {
                read(x);
                //scanf("%d",&x);
                num[p]=x;
                lstch[p]=i;
            }
            else
            {
                while(top&&p>=sta[top])
                    --top;
                sta[++top]=p;
                add[top]=i;
            }
        }
        sta[++top]=0;
        add[top]=m+1;
        for(int i=1;i<=n;++i)
            num[i]=max(num[i],sta[lower_bound(add+1,add+top+1,lstch[i])-add]);
        for(int i=1;i<=n;++i)
            write(num[i]),putchar(i==n?'
    ':' ');
        return 0;
    }
    
  • 相关阅读:
    C++11 新特性之 变长參数模板
    Cocos2dx 3.6源代码编译错误:syntax error : missing &#39;)&#39; before &#39;{&#39;
    android开发中,在java中怎样使用c提供过来char*
    cocos2d-x 3.1.1 学习笔记[11] http请求 + json解析
    T420s成功加装固态硬盘(SSD)
    我对GFWed的一些自己的见解
    css样式布局中position的那些事儿
    Tokyo Tyrant(TTServer)系列(一)-介绍和安装
    Linux 文件描述符和重定向
    装饰模式
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11288763.html
Copyright © 2011-2022 走看看