HDU3991:Black and White

浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3911

用线段树维护六个信息,分别是区间最长子段,最左边连续的最长段,最右边连续的最长段,然后分\(0\)\(1\)分别处理出来。询问的时候因为会先访问最左边的段,然后依次往右走,所以开一个全局变量存上一段最右一段\(1\)有多长,然后和当前段合并起来更新答案就行。

时间复杂度:\(O(mlogn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
 
const int maxn=1e5+5;
 
int a[maxn];
int n,m,ans,mx;
 
int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
 
struct tree_node {
    int mx[2],lft[2],rgt[2];
};
 
struct segment_tree {
    bool rev[maxn<<2];
    tree_node tree[maxn<<2];
     
    void updata(int p,int l,int r) {
        int mid=(l+r)>>1;
        for(int i=0;i<2;i++) {
            tree[p].mx[i]=max(tree[p<<1].rgt[i]+tree[p<<1|1].lft[i],max(tree[p<<1].mx[i],tree[p<<1|1].mx[i]));
            if(tree[p<<1].lft[i]==mid-l+1)tree[p].lft[i]=tree[p<<1].lft[i]+tree[p<<1|1].lft[i];
            else tree[p].lft[i]=tree[p<<1].lft[i];
            if(tree[p<<1|1].rgt[i]==r-mid)tree[p].rgt[i]=tree[p<<1].rgt[i]+tree[p<<1|1].rgt[i];
            else tree[p].rgt[i]=tree[p<<1|1].rgt[i];
        }
    }
     
    void add_tag(int p) {
        rev[p]^=1;
        swap(tree[p].mx[0],tree[p].mx[1]);
        swap(tree[p].lft[0],tree[p].lft[1]);
        swap(tree[p].rgt[0],tree[p].rgt[1]);
    }
 
    void push_down(int p) {
        if(rev[p]) {
            add_tag(p<<1);
            add_tag(p<<1|1);
            rev[p]=0;
        }
    }
 
    void build(int p,int l,int r) {
        rev[p]=0;
        for(int i=0;i<2;i++)
            tree[p].mx[i]=tree[p].lft[i]=tree[p].rgt[i]=0;//多组数据要记得清空
        if(l==r) {
            tree[p].mx[a[l]]=1;
            tree[p].lft[a[l]]=1;
            tree[p].rgt[a[l]]=1;
            return;
        }
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
        updata(p,l,r);
    }
 
    void rever(int p,int l,int r,int L,int R) {
        if(L<=l&&r<=R) {
            add_tag(p);
            return;
        }
        int mid=(l+r)>>1;push_down(p);
        if(L<=mid)rever(p<<1,l,mid,L,R);
        if(R>mid)rever(p<<1|1,mid+1,r,L,R);
        updata(p,l,r);
    }
     
    void query(int p,int l,int r,int L,int R) {
        if(L<=l&&r<=R) {
            ans+=tree[p].lft[1];
            mx=max(mx,max(tree[p].mx[1],ans));
            if(tree[p].lft[1]!=r-l+1)ans=tree[p].rgt[1];
            return;
        }
        int mid=(l+r)>>1;push_down(p);
        if(L<=mid)query(p<<1,l,mid,L,R);
        if(R>mid)query(p<<1|1,mid+1,r,L,R);
    }
}T;
 
int main() {
    while(~scanf("%d",&n)) {
        for(int i=1;i<=n;i++)
            a[i]=read();
        T.build(1,1,n);m=read();
        for(int i=1;i<=m;i++) {
            int opt=read(),l=read(),r=read();
            if(opt==1)T.rever(1,1,n,l,r);
            else {
                ans=mx=0;
                T.query(1,1,n,l,r);
                printf("%d\n",mx);
            }
        }
    }
    return 0;
}
posted @ 2018-11-13 10:00  AKMer  阅读(136)  评论(0编辑  收藏  举报