传送门:CDOJ1592


题目大意

给你一个长度为n的序列,只有1和0,m次操作,两种操作,第一种为将一段区间异或上0,

一种为询问一段区间最长连续1的长度


题目思路:

这是线段树区间合并的模板题,在普通线段树上改进下维护每个区间向左向右连续1和0的长度

和区间最长连续的长度,这样向上更新的时候为 ,左右连续等于子区间连续,如果左右连续填

满了子区间,则还要加上相反连续的和,例如子区间的向左连续为区间长度,则父区间的向左

连续为子区间左连续加上子右区间的左连续,然后最大连续为左右子区间和中间连续的最大值

向下更新为记录个懒惰标记,每次将子区间的连续0和1交换,因为是异或,0变1,1变0,

更新的时候写法差不多,查询的时候则要返回两边最大和中间连续的最大值


AC代码:


/**
CDOJ1592 线段树区间合并模板题  HDU3911
*/


#include<bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
const int maxn = 1e5+100;

struct ST
{
    int lone,rone,lzero,rzero,sumone,sumzero;
    int cover;
    int l,r;
}Tree[maxn<<2];

int n;


//向上更新
void push_up(int rt)
{
    Tree[rt].lone = Tree[rt<<1].lone;
    Tree[rt].lzero = Tree[rt<<1].lzero;

    
    //子区间填满
    if(Tree[rt<<1].lone==Tree[rt<<1].r-Tree[rt<<1].l+1)Tree[rt].lone+=Tree[rt<<1|1].lone;
    if(Tree[rt<<1].lzero==Tree[rt<<1].r-Tree[rt<<1].l+1)Tree[rt].lzero+=Tree[rt<<1|1].lzero;

    Tree[rt].rone = Tree[rt<<1|1].rone;
    Tree[rt].rzero = Tree[rt<<1|1].rzero;

    if(Tree[rt<<1|1].rone==Tree[rt<<1|1].r-Tree[rt<<1|1].l+1)Tree[rt].rone+=Tree[rt<<1].rone;
    if(Tree[rt<<1|1].rzero==Tree[rt<<1|1].r-Tree[rt<<1|1].l+1)Tree[rt].rzero+=Tree[rt<<1].rzero;

    Tree[rt].sumone = max(Tree[rt<<1].rone+Tree[rt<<1|1].lone,max(Tree[rt<<1].sumone,Tree[rt<<1|1].sumone));
    Tree[rt].sumzero = max(Tree[rt<<1].rzero+Tree[rt<<1|1].lzero,max(Tree[rt<<1].sumzero,Tree[rt<<1|1].sumzero));
}

void Build(int l,int r,int rt)
{
    Tree[rt].l = l,Tree[rt].r = r,Tree[rt].cover = 0;
    if(l==r)
    {
        int x;scanf("%d",&x);
        Tree[rt].lone = Tree[rt].rone = Tree[rt].sumone = x;
        Tree[rt].lzero = Tree[rt].rzero = Tree[rt].sumzero = !x;
        return ;
    }
    int mid = (l+r)>>1;
    Build(lson);
    Build(rson);
    push_up(rt);
}

void pushdown(int rt)
{
    if(Tree[rt].cover)
    {
        Tree[rt<<1].cover^=1;
        Tree[rt<<1|1].cover^=1;
        Tree[rt].cover = 0;
        
        //0,1交换
        swap(Tree[rt<<1].lone,Tree[rt<<1].lzero);
        swap(Tree[rt<<1].sumone,Tree[rt<<1].sumzero);
        swap(Tree[rt<<1].rone,Tree[rt<<1].rzero);

        swap(Tree[rt<<1|1].lone,Tree[rt<<1|1].lzero);
        swap(Tree[rt<<1|1].sumone,Tree[rt<<1|1].sumzero);
        swap(Tree[rt<<1|1].rone,Tree[rt<<1|1].rzero);
    }
}

void updata(int l,int r,int rt)
{
    if(l<=Tree[rt].l&&Tree[rt].r<=r)
    {
        Tree[rt].cover^=1;
        swap(Tree[rt].lone,Tree[rt].lzero);
        swap(Tree[rt].sumone,Tree[rt].sumzero);
        swap(Tree[rt].rone,Tree[rt].rzero);
        return ;
    }
    pushdown(rt);
    int mid = (Tree[rt].r+Tree[rt].l)>>1;
    if(r<=mid)
    {
        updata(l,r,rt<<1);
    }
    else if(l>mid)
    {
       updata(l,r,rt<<1|1);
    }
    else
    {
        updata(l,mid,rt<<1);
        updata(mid+1,r,rt<<1|1);
    }
    push_up(rt);
}

int quary(int l,int r,int rt)
{
    if(l<=Tree[rt].l&&Tree[rt].r<=r)
    {
        return Tree[rt].sumone;
    }
    pushdown(rt);
    int mid = (Tree[rt].r+Tree[rt].l)>>1;
    if(l>mid)return quary(l,r,rt<<1|1);
    else if(r<=mid)return quary(l,r,rt<<1);
    else
    {
        int ans1 = quary(l,mid,rt<<1);
        int ans2 = quary(mid+1,r,rt<<1|1);
        return max(min(mid-l+1,Tree[rt<<1].rone)+min(r-mid,Tree[rt<<1|1].lone),max(ans1,ans2));
    }
}

int main()
{
    int m;
    while(cin>>n)
    {
        Build(1,n,1);
        cin>>m;
        while(m--)
        {
            int id,x,y;
            scanf("%d%d%d",&id,&x,&y);
            if(id)
            {
                updata(x,y,1);
            }
            else
            {
                printf("%d\n",quary(x,y,1));
            }
        }
    }

    return 0;
}