[BZOJ1858]序列操作 線段樹

BZOJ1858
這題是不錯的線段樹練習題.
注意查詢的時候返回一個節點而不是一個具體的數,否則無法做到合併信息並上傳.
還好一個小時就寫完啦

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,m,a[maxn];
struct tree{
    int l,r,l0,r0,z0,l1,r1,z1,num0,num1,sum1,sum0,tag;
    bool rev;
    tree*ls,*rs;
    tree()
    {
        tag=-1;
        rev=false;
        l=r=l0=r0=z0=l1=r1=z1=num0=num1=sum1=sum0=0;
        ls=rs=NULL;
    }
    void update()
    {
        l1=ls->l1+(ls->l1==ls->r-ls->l+1)*(rs->l1);
        r1=rs->r1+(rs->r1==rs->r-rs->l+1)*(ls->r1);
        l0=ls->l0+(ls->l0==ls->r-ls->l+1)*(rs->l0);
        r0=rs->r0+(rs->r0==rs->r-rs->l+1)*(ls->r0);
        z0=max(max(ls->z0,rs->z0),ls->r0+rs->l0);
        z1=max(max(ls->z1,rs->z1),ls->r1+rs->l1);
        num0=max(ls->r0+rs->l0,max(ls->z0,rs->z0));
        num1=max(ls->r1+rs->l1,max(ls->z1,rs->z1));
        sum1=ls->sum1+rs->sum1;
        sum0=ls->sum0+rs->sum0;
    }
    void calc(int v)
    {
        rev=false;
        tag=v;
        if(v==0)
        {
        sum1=num1=l1=r1=z1=0;
        sum0=num0=l0=r0=z0=r-l+1;
        }
        if(v==1)
        {
        sum1=num1=l1=r1=z1=r-l+1;
        sum0=num0=l0=r0=z0=0;
        }
    }
    void calcrev()
    {
        rev=!rev;
        swap(l1,l0);swap(z1,z0);swap(r1,r0);
        swap(sum1,sum0);swap(num1,num0);
    }
    void pushdown()
    {
        if(tag==0)
        {
            ls->calc(0);
            rs->calc(0);
            tag=-1;
        }
        if(tag==1)
        {
            ls->calc(1);
            rs->calc(1);
            tag=-1;
        }
        if(rev)
        {
            ls->calcrev();
            rs->calcrev();
            rev=false;
        }
    }
    void build(int lx,int rx)
    {
        l=lx;r=rx;
        if(l==r) 
        {
            if(a[l]==1)
            num0=sum0=l0=r0=z0=0,num1=sum1=l1=r1=z1=1;
            else num0=sum0=l0=r0=z0=1,num1=sum1=l1=r1=z1=0;
            return;
        }
        int mid=(l+r)>>1;
        (ls=new tree)->build(l,mid);
        (rs=new tree)->build(mid+1,r);
        update();
    }
    void mod(int lx,int rx,int num)
    {
        if(l==lx&&r==rx)
        {
            if(num!=-1)
                calc(num);
            else calcrev();
            return;
        }
        pushdown();
        int mid=(l+r)>>1;
        if(lx>mid) rs->mod(lx,rx,num);
        else if(rx<=mid) ls->mod(lx,rx,num);
        else ls->mod(lx,mid,num),rs->mod(mid+1,rx,num);
        update();
    }
    int que1(int lx,int rx)
    {
        if(l==lx&&r==rx)
            return sum1;
        pushdown();
        int mid=(l+r)>>1;
        if(lx>mid) return rs->que1(lx,rx);
        else if(rx<=mid) return ls->que1(lx,rx);
        else return ls->que1(lx,mid)+rs->que1(mid+1,rx);
    }
    tree* quel1(int lx,int rx)
    {
        if(l==lx&&r==rx)
        return this;
        pushdown();
            int mid=(l+r)>>1;
            if(lx>mid) return rs->quel1(lx,rx);
            else if(rx<=mid) return ls->quel1(lx,rx);
            else
            {
            tree*p1=ls->quel1(lx,mid),*p2=rs->quel1(mid+1,rx);
            tree*p=new tree;
            p->l1=p1->l1+(p1->l1==p1->r-p1->l+1)*(p2->l1);
            p->r1=p2->r1+(p2->r1==p2->r-p2->l+1)*(p1->r1);
            p->l0=p1->l0+(p1->l0==p1->r-p1->l+1)*(p2->l0);
            p->r0=p2->r0+(p2->r0==p2->r-p2->l+1)*(p1->r0);
            p->z0=max(max(p1->z0,p2->z0),p1->r0+p2->l0);
            p->z1=max(max(p1->z1,p2->z1),p1->r1+p2->l1);
            p->num0=max(p1->r0+p2->l0,max(p1->z0,p2->z0));
            p->num1=max(p1->r1+p2->l1,max(p1->z1,p2->z1));
            p->sum1=p1->sum1+p2->sum1;
            p->sum0=p1->sum0+p2->sum0;
            return p;
            }           
    }
    void oupt()
    {
        cout<<l<<" "<<r<<" "<<l1<<" "<<z1<<" "<<r1<<endl;
        if(l==r) return;
        ls->oupt();
        rs->oupt();
    }
}*xtr;
int main()
{
//  freopen("data.in","r",stdin);
//  freopen("wode.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    scanf("%d",&a[i]);
    (xtr=new tree)->build(1,n);
    int x,y,opt;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&opt,&x,&y);
        x++;y++;
        if(opt==0) xtr->mod(x,y,0);
        if(opt==1) xtr->mod(x,y,1);
        if(opt==2) xtr->mod(x,y,-1);
        if(opt==3) printf("%d\n",xtr->que1(x,y));
        if(opt==4) printf("%d\n",xtr->quel1(x,y)->num1);
    }
return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章