[BZOJ 1858][Scoi2010]序列操作(線段樹)

Description


lxhgww最近收到了一個01序列,序列裏面包含了n個數,這些數要麼是0,要麼是1,現在對於這個序列有五種變換操作和詢問操作: 0 a b 把[a, b]區間內的所有數全變成0 1 a b 把[a, b]區間內的所有數全變成1 2 a b 把[a,b]區間內的所有數全部取反,也就是說把所有的0變成1,把所有的1變成0 3 a b 詢問[a, b]區間內總共有多少個1 4 a b 詢問[a, b]區間內最多有多少個連續的1 對於每一種詢問操作,lxhgww都需要給出回答,聰明的程序員們,你們能幫助他嗎?

Input


輸入數據第一行包括2個數,n和m,分別表示序列的長度和操作數目 第二行包括n個數,表示序列的初始狀態 接下來m行,每行3個數,op, a, b,(0<=op<=4,0<=a<=b

Output


對於每一個詢問操作,輸出一行,包括1個數,表示其對應的答案

Sample Input


10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9

Sample Output


5
2
6
5

HINT


對於30%的數據,1<=n, m<=1000
對於100%的數據,1<=n, m<=100000

Solution


啊爲什麼調了那麼長時間…
後來發現是push_down操作給子節點標lazy的時候忘記把它們的rev標記去掉了 淚

線段記錄區間裏1和0的個數、最長連續的1和0的個數、左端連續的1和0的個數、右端連續的1和0的個數,然後記錄一個lazy標記和rev標記(取反)。
取反操作的時候遇到lazy標記可以直接對lazy取反,標記lazy的時候要記得把rev去掉
那個最長連續1的詢問函數直接返回了一個結構體,合併操作和線段樹的更新差不多,具體實現看代碼

感覺我沒有辦法寫出優美的代碼,不知道爲什麼代碼長度這麼長= =

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<assert.h>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define mid(a,b) ((a+b)>>1)
#define MAXN 100005
using namespace std;
int n,m;
int x[MAXN],ans;
struct Node{
    int l,r,siz;
    int num1,lnum1,rnum1,maxnum1;
    int num0,lnum0,rnum0,maxnum0;
    int lazy,rev;
}t[MAXN*4];
Node operator + (const Node& a,const Node& b)
{
    Node ans;

    ans.lnum0=a.lnum0;
    if(a.lnum0==a.siz)
    ans.lnum0=a.siz+b.lnum0;
    ans.lnum1=a.lnum1;
    if(a.lnum1==a.siz)
    ans.lnum1=a.siz+b.lnum1;

    ans.rnum0=b.rnum0;
    if(b.rnum0==b.siz)
    ans.rnum0=b.siz+a.rnum0;
    ans.rnum1=b.rnum1;
    if(b.rnum1==b.siz)
    ans.rnum1=b.siz+a.rnum1;

    ans.num0=a.num0+b.num0;
    ans.num1=a.num1+b.num1;

    ans.maxnum0=Max(a.maxnum0,b.maxnum0);
    ans.maxnum0=Max(ans.maxnum0,a.rnum0+b.lnum0);

    ans.maxnum1=Max(a.maxnum1,b.maxnum1);
    ans.maxnum1=Max(ans.maxnum1,a.rnum1+b.lnum1);
    return ans;
}
void _exchange(int idx)
{
    swap(t[idx].lnum0,t[idx].lnum1);
    swap(t[idx].rnum0,t[idx].rnum1);
    swap(t[idx].num0,t[idx].num1);
    swap(t[idx].maxnum0,t[idx].maxnum1);
}
void push_down(int idx)
{
    if(t[idx].l==t[idx].r)return;
    if(t[idx].lazy!=-1)
    {
        int f=t[idx].lazy;
        t[idx*2].lazy=t[idx*2+1].lazy=t[idx].lazy;
        t[idx*2].rev=t[idx*2+1].rev=0;
        t[idx].lazy=-1;
        t[idx*2].lnum0=t[idx*2].rnum0=t[idx*2].num0=t[idx*2].maxnum0=(f==0)*t[idx*2].siz;
        t[idx*2].lnum1=t[idx*2].rnum1=t[idx*2].num1=t[idx*2].maxnum1=(f==1)*t[idx*2].siz;
        t[idx*2+1].lnum0=t[idx*2+1].rnum0=t[idx*2+1].num0=t[idx*2+1].maxnum0=(f==0)*t[idx*2+1].siz;
        t[idx*2+1].lnum1=t[idx*2+1].rnum1=t[idx*2+1].num1=t[idx*2+1].maxnum1=(f==1)*t[idx*2+1].siz;
    }
    if(t[idx].rev)
    {
        t[idx].rev=0;
        t[idx*2].rev^=1;
        t[idx*2+1].rev^=1;
        _exchange(idx*2);
        _exchange(idx*2+1);
    }
}
void _update(int idx)
{
    t[idx].lnum0=t[idx*2].lnum0;
    if(t[idx*2].lnum0==t[idx*2].siz)
    t[idx].lnum0=t[idx*2].siz+t[idx*2+1].lnum0;
    t[idx].lnum1=t[idx*2].lnum1;
    if(t[idx*2].lnum1==t[idx*2].siz)
    t[idx].lnum1=t[idx*2].siz+t[idx*2+1].lnum1;

    t[idx].rnum0=t[idx*2+1].rnum0;
    if(t[idx*2+1].rnum0==t[idx*2+1].siz)
    t[idx].rnum0=t[idx*2+1].siz+t[idx*2].rnum0;
    t[idx].rnum1=t[idx*2+1].rnum1;
    if(t[idx*2+1].rnum1==t[idx*2+1].siz)
    t[idx].rnum1=t[idx*2+1].siz+t[idx*2].rnum1;

    t[idx].num0=t[idx*2].num0+t[idx*2+1].num0;
    t[idx].num1=t[idx*2].num1+t[idx*2+1].num1;

    t[idx].maxnum0=Max(t[idx*2].maxnum0,t[idx*2+1].maxnum0);
    t[idx].maxnum0=Max(t[idx].maxnum0,t[idx*2].rnum0+t[idx*2+1].lnum0);

    t[idx].maxnum1=Max(t[idx*2].maxnum1,t[idx*2+1].maxnum1);
    t[idx].maxnum1=Max(t[idx].maxnum1,t[idx*2].rnum1+t[idx*2+1].lnum1);
}
void _build(int idx,int a,int b)
{
    t[idx].siz=b-a+1;
    t[idx].l=a;t[idx].r=b;
    t[idx].lazy=-1;
    t[idx].rev=0;
    if(a==b)
    {
        if(x[a])
        {
            t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=0;
            t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=1;
        }
        else 
        {
            t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=1;
            t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=0;
        }
        return;
    }
    int m=mid(a,b);
    _build(idx*2,a,m);
    _build(idx*2+1,m+1,b);
    _update(idx);
}
void _turn(int idx,int a,int b,int f)
{
    push_down(idx);
    if(t[idx].l==t[idx].r)
    {
        t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0);
        t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1);
        return;
    }
    if(a<=t[idx].l&&b>=t[idx].r)
    {
        t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0)*t[idx].siz;
        t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1)*t[idx].siz;
        if(t[idx].rev)
        t[idx].rev=0;
        t[idx].lazy=f;
        return;
    }

    int m=mid(t[idx].l,t[idx].r);
    if(b<=m)_turn(idx*2,a,b,f);
    else if(a>m)_turn(idx*2+1,a,b,f);
    else
    {
        _turn(idx*2,a,b,f);
        _turn(idx*2+1,a,b,f);
    }
    _update(idx);
}
void _reverse(int idx,int a,int b)
{
    push_down(idx);
    if(t[idx].l==t[idx].r)
    {
        _exchange(idx);
        return;
    }
    if(a<=t[idx].l&&b>=t[idx].r)
    {
        if(t[idx].lazy!=-1)
        {
            t[idx].lazy^=1;
            _exchange(idx);
            return;
        }
        t[idx].rev^=1;
        _exchange(idx);
        return;
    }
    int m=mid(t[idx].l,t[idx].r);
    if(b<=m)_reverse(idx*2,a,b);
    else if(a>m)_reverse(idx*2+1,a,b);
    else
    {
        _reverse(idx*2,a,b);
        _reverse(idx*2+1,a,b);
    }
    _update(idx);
}
void _count(int idx,int a,int b)
{
    push_down(idx);
    if(t[idx].l==t[idx].r)
    {
        ans+=t[idx].num1;
        return;
    }

    if(a<=t[idx].l&&b>=t[idx].r)
    {
        ans+=t[idx].num1;
        return;
    }

    int m=mid(t[idx].l,t[idx].r);
    if(b<=m)_count(idx*2,a,b);
    else if(a>m)_count(idx*2+1,a,b);
    else
    {
        _count(idx*2,a,b);
        _count(idx*2+1,a,b);
    }
}
Node _query(int idx,int a,int b)
{
    push_down(idx);
    if(a==t[idx].l&&b==t[idx].r)
    {
        return t[idx];
    }

    int m=mid(t[idx].l,t[idx].r);
    if(a<=m&&b>m)
    {
        return _query(idx*2,a,m)+_query(idx*2+1,m+1,b);
    }
    if(a>m)
    {
        return _query(idx*2+1,a,b);
    }
    if(b<=m)
    {
        return _query(idx*2,a,b);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    scanf("%d",&x[i]);
    _build(1,0,n-1);
    for(int i=1;i<=m;i++)
    {
        int opt,a,b;
        scanf("%d%d%d",&opt,&a,&b);
        switch(opt)
        {
            case 0:
            _turn(1,a,b,0);break;
            case 1:
            _turn(1,a,b,1);break;   
            case 2:
            _reverse(1,a,b);break;
            case 3:
            ans=0;_count(1,a,b);printf("%d\n",ans);break;
            case 4:
            Node res=_query(1,a,b);
            printf("%d\n",res.maxnum1);break;

        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章