bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj千题计划177:bzoj1858: [Scoi2010]序列操作相关的知识,希望对你有一定的参考价值。

http://www.lydsy.com/JudgeOnline/problem.php?id=1858

 

2018 自己写的第1题,一遍过

^_^

元旦快乐

 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001

struct node
{
    int siz;
    int L[2],R[2],con[2];
    int sum[2];
    bool rev;
    int cover;
}tr[N<<2];

struct node_
{
    int L1,R1,con1;
    int siz;
};

node_ operator + (node_ l,node_ r)
{
    node_ res;
    res.L1=l.L1;
    if(l.L1==l.siz) res.L1+=r.L1;
    res.R1=r.R1;
    if(r.R1==r.siz) res.R1+=l.R1;
    res.con1=max(l.con1,r.con1);
    res.con1=max(res.con1,l.R1+r.L1);
    return res;
}

int x;

int ans;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}

void update(int k)
{
    for(int i=0;i<=1;++i)
    {
        tr[k].L[i]=tr[k<<1].L[i];
        if(tr[k<<1].L[i]==tr[k<<1].siz) tr[k].L[i]+=tr[k<<1|1].L[i];
        tr[k].R[i]=tr[k<<1|1].R[i];
        if(tr[k<<1|1].R[i]==tr[k<<1|1].siz) tr[k].R[i]+=tr[k<<1].R[i];
        tr[k].con[i]=max(tr[k<<1].con[i],tr[k<<1|1].con[i]);
        tr[k].con[i]=max(tr[k].con[i],tr[k<<1].R[i]+tr[k<<1|1].L[i]);
        tr[k].sum[i]=tr[k<<1].sum[i]+tr[k<<1|1].sum[i];
    }
}

void build(int k,int l,int r)
{
    tr[k].cover=-1;
    tr[k].siz=r-l+1;
    if(l==r)
    {
        read(x);
        tr[k].L[x]++;
        tr[k].R[x]++;
        tr[k].con[x]++;
        tr[k].sum[x]++;
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    update(k);
}

void reverse(int k)
{
    swap(tr[k].L[0],tr[k].L[1]);
    swap(tr[k].R[0],tr[k].R[1]);
    swap(tr[k].con[0],tr[k].con[1]);
    swap(tr[k].sum[0],tr[k].sum[1]);
    tr[k].rev^=1;
    if(tr[k].cover!=-1) tr[k].cover^=1;
}

void down_rev(int k)
{
    reverse(k<<1);
    reverse(k<<1|1);
    tr[k].rev^=1;
}

void covering(int k,int w)
{
    tr[k].L[w]=tr[k].R[w]=tr[k].con[w]=tr[k].sum[w]=tr[k].siz;
    tr[k].L[w^1]=tr[k].R[w^1]=tr[k].con[w^1]=tr[k].sum[w^1]=0;
    tr[k].cover=w;
    tr[k].rev=false;
}

void down_cov(int k)
{
    covering(k<<1,tr[k].cover);
    covering(k<<1|1,tr[k].cover);
    tr[k].cover=-1;
}

void Cover(int k,int l,int r,int opl,int opr,int w)
{
    if(l>=opl && r<=opr)
    {
        covering(k,w);
        return;
    }
    if(tr[k].rev) down_rev(k);
    if(tr[k].cover!=-1) down_cov(k);
    int mid=l+r>>1;
    if(opl<=mid) Cover(k<<1,l,mid,opl,opr,w);
    if(opr>mid) Cover(k<<1|1,mid+1,r,opl,opr,w);
    update(k);
}

void Reverse(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr)
    {
        reverse(k);
        return;
    }
    if(tr[k].rev) down_rev(k);
    if(tr[k].cover!=-1) down_cov(k);
    int mid=l+r>>1;
    if(opl<=mid) Reverse(k<<1,l,mid,opl,opr);
    if(opr>mid) Reverse(k<<1|1,mid+1,r,opl,opr);
    update(k);
}

void query(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr)
    {
        ans+=tr[k].sum[1];
        return;
    }
    if(tr[k].rev) down_rev(k);
    if(tr[k].cover!=-1) down_cov(k);
    int mid=l+r>>1;
    if(opl<=mid) query(k<<1,l,mid,opl,opr);
    if(opr>mid) query(k<<1|1,mid+1,r,opl,opr);
}

node_ Query(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr)
    {
        node_ res;
        res.L1=tr[k].L[1];
        res.R1=tr[k].R[1];
        res.con1=tr[k].con[1];
        res.siz=tr[k].siz;
        return res;
    }
    if(tr[k].rev) down_rev(k);
    if(tr[k].cover!=-1) down_cov(k);
    int mid=l+r>>1;
    if(opr<=mid) return Query(k<<1,l,mid,opl,opr);
    if(opl>mid) return Query(k<<1|1,mid+1,r,opl,opr);
    return Query(k<<1,l,mid,opl,opr)+Query(k<<1|1,mid+1,r,opl,opr);
}

int main()
{
    int n,m;
    read(n); read(m);
    build(1,1,n);
    int ty,l,r;
    while(m--)
    {
        read(ty); read(l); read(r);
        l++; r++;
        switch(ty)
        {
            case 0 : Cover(1,1,n,l,r,0); break;
            case 1 : Cover(1,1,n,l,r,1); break;
            case 2 : Reverse(1,1,n,l,r); break;
            case 3 : ans=0; query(1,1,n,l,r); cout<<ans<<\n; break;
            case 4 : printf("%d\n",Query(1,1,n,l,r).con1); break;
        }
    }
}

 

以上是关于bzoj千题计划177:bzoj1858: [Scoi2010]序列操作的主要内容,如果未能解决你的问题,请参考以下文章

bzoj千题计划197:bzoj4247: 挂饰

bzoj千题计划118:bzoj1028: [JSOI2007]麻将

bzoj千题计划165:bzoj5127: 数据校验

bzoj千题计划144:bzoj1176: [Balkan2007]Mokia

bzoj千题计划142:bzoj3144: [Hnoi2013]切糕

bzoj千题计划242:bzoj4034: [HAOI2015]树上操作