zoukankan      html  css  js  c++  java
  • bzoj1858 [Scoi2010]序列操作——线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858

    线段树...调了一个上午...(后面带 // 的都是改出来的)

    lazy 标记的下放好麻烦,还得考虑赋值和取反的先后顺序什么的...

    因为在取反时把赋值标记 swap 了,所以下放的时候先判断取反再判断赋值...

    而且WA了一上午的原因竟然是一开始不慎把取反以为成翻转了,后来没改干净...那个 rev 的名字啊...

    总之没有太改变自己最初的想法、改了些细节就A了还是很高兴的!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=1e5+5;
    int n,m,op,a,b,c[maxn];
    struct N{
        int sum,z[3],y[3],m[3];
        int lz[3],rev,len;
    }t[maxn<<2];
    int rd()
    {
        int ret=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
        return ret;
    }
    void pushup(int x)
    {
        int ls=(x<<1),rs=(x<<1|1);
        t[x].sum=t[ls].sum+t[rs].sum;
        for(int i=0;i<=1;i++)
        {
            t[x].z[i]=t[ls].z[i]+(t[ls].z[i]==t[ls].len?t[rs].z[i]:0);
            t[x].y[i]=t[rs].y[i]+(t[rs].y[i]==t[rs].len?t[ls].y[i]:0);
    //        t[x].m[i]=max(max(t[x].z[i],t[x].y[i]),t[ls].y[i]+t[rs].z[i]);//
            t[x].m[i]=max(max(t[ls].m[i],t[rs].m[i]),t[ls].y[i]+t[rs].z[i]);//
        }
    }
    void upt(int x,int val)//赋值 
    {
        t[x].lz[val]=1;
        t[x].lz[!val]=0; t[x].rev=0;//!
        t[x].sum=t[x].len*val; 
        t[x].z[val]=t[x].y[val]=t[x].m[val]=t[x].len;
        t[x].z[!val]=t[x].y[!val]=t[x].m[!val]=0;
    }
    void re(int x)//取反 
    {
        swap(t[x].z[0],t[x].z[1]); swap(t[x].y[1],t[x].y[0]);//!!!
        swap(t[x].m[1],t[x].m[0]);
        t[x].sum=t[x].len-t[x].sum; t[x].rev^=1;
        swap(t[x].lz[1],t[x].lz[0]);//!
    }
    void pushdown(int x)
    {
    //    if(t[x].len==1)return;//
        int ls=(x<<1),rs=(x<<1|1);
        if(t[x].rev)t[x].rev^=1,re(ls),re(rs);
        for(int v=0;v<=1;v++)
            if(t[x].lz[v])t[x].lz[v]=0,upt(ls,v),upt(rs,v);//顺序 
    }
    void build(int x,int l,int r)
    {
        t[x].len=r-l+1;
        if(l==r)
        {
            t[x].z[c[l]]=t[x].y[c[l]]=t[x].m[c[l]]=1;
            t[x].sum=c[l]; //
            return;
        }
        int mid=((l+r)>>1);
        build(x<<1,l,mid); build(x<<1|1,mid+1,r);
        pushup(x);
    }
    void update(int x,int l,int r,int L,int R,int val)
    {
        if(l>=L&&r<=R)
        {
            upt(x,val);return;
        }
        pushdown(x);
        int mid=((l+r)>>1);
        if(mid>=L)update(x<<1,l,mid,L,R,val);
        if(mid<R)update(x<<1|1,mid+1,r,L,R,val);
        pushup(x);
    }
    void rever(int x,int l,int r,int L,int R)
    {
        if(l>=L&&r<=R)
        {
            re(x);return;
        }
        int mid=((l+r)>>1);
        pushdown(x);
        if(mid>=L)rever(x<<1,l,mid,L,R);
        if(mid<R)rever(x<<1|1,mid+1,r,L,R);
        pushup(x);
    }
    int query(int x,int l,int r,int L,int R)
    {
        if(l>=L&&r<=R)return t[x].sum;
        int mid=((l+r)>>1),ret=0;
        pushdown(x);
        if(mid>=L)ret+=query(x<<1,l,mid,L,R);
        if(mid<R)ret+=query(x<<1|1,mid+1,r,L,R);
        return ret;
    }
    int ask(int x,int l,int r,int L,int R)
    {
        if(l>=L&&r<=R)return t[x].m[1];
        pushdown(x);//
        int mid=((l+r)>>1);
        if(mid>=R)return ask(x<<1,l,mid,L,R);
        if(mid<L)return ask(x<<1|1,mid+1,r,L,R);
        int ret=0;
        ret=max(ask(x<<1,l,mid,L,R),ask(x<<1|1,mid+1,r,L,R));
        ret=max(ret,min(t[x<<1].y[1],mid-L+1)+min(t[x<<1|1].z[1],R-mid));
        return ret;
    }
    int main()
    {
        n=rd();m=rd();
        for(int i=1;i<=n;i++)c[i]=rd();
        build(1,1,n);
        while(m--)
        {
            op=rd(); a=rd()+1; b=rd()+1;
            if(op==0||op==1)update(1,1,n,a,b,op);
            if(op==2)rever(1,1,n,a,b);
            if(op==3)printf("%d
    ",query(1,1,n,a,b));
            if(op==4)printf("%d
    ",ask(1,1,n,a,b));
        }
        return 0;
    } 
  • 相关阅读:
    Linux命令笔记
    拆功放板笔记
    从输入 URL 到页面加载完的过程中都发生了什么---优化
    python学习笔记(三)
    python学习笔记(二)
    python学习笔记(一)
    公交wifi运营平台分析
    testNG小试牛刀
    maven小项目注册服务(三)--web模块
    用maven进行测试
  • 原文地址:https://www.cnblogs.com/Zinn/p/9186579.html
Copyright © 2011-2022 走看看