题目大意:
给你一个长为n的01序列,实现两种操作:$(0,l,r)$,询问区间$[l,r]$中连续的全1序列的最长长度;$(1,l,r)$,将区间$[l,r]$中每个数取反,即异或1。$(n,m\le10^5)$
解题思路:
实际上,这就是一道线段树的区间合并问题,每个节点维护一下Tlen该区间最长连续全1序列长度,Llen,Rlen,即左右的全1序列长度。那么新奇的是第二个操作,其实你只要对于0和1都维护一下就好了,翻转时交换两个值就好了。呵呵,我调了1个晚上没有调出来,写了拍才拍出些错。主要是我前一道题抄了别人代码,导致我的线段树lazy标记下移的写法产生了混乱,所以,不到万不得已不要看别人的代码。
代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define MAXN 400005
#define L(a) ((a)<<1)
#define R(a) ((a)<<1|1)
using namespace std;
inline int read() {
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int n, m, a[100005];
struct Segment_Tree {
    int Le[MAXN], Re[MAXN];
    bool Lazy[MAXN];
    int BTlen[MAXN], BLlen[MAXN], BRlen[MAXN];
    int WTlen[MAXN], WLlen[MAXN], WRlen[MAXN];
    
    inline int len(int p) { return Re[p]-Le[p]+1; }
    
    void Update_len(int p) {
        swap(BTlen[p], WTlen[p]);
        swap(BLlen[p], WLlen[p]);
        swap(BRlen[p], WRlen[p]);
    }
    
    void Pushdown(int p) {
        if(Le[p] == Re[p] || !Lazy[p]) return;
        Lazy[L(p)] ^= 1;  Lazy[R(p)] ^= 1;
        Lazy[p] = false;
        Update_len(L(p)); Update_len(R(p));
    }
    
    void Update(int p) {
        if(Le[p] == Re[p]) return;
        BTlen[p] = max(BTlen[L(p)], BTlen[R(p)]);
        BTlen[p] = max(BTlen[p], BRlen[L(p)] + BLlen[R(p)]);
        BLlen[p] = BLlen[L(p)]; if(BLlen[L(p)] == len(L(p))) BLlen[p] += BLlen[R(p)];
        BRlen[p] = BRlen[R(p)]; if(BRlen[R(p)] == len(R(p))) BRlen[p] += BRlen[L(p)];
        
        WTlen[p] = max(WTlen[L(p)], WTlen[R(p)]);
        WTlen[p] = max(WTlen[p], WRlen[L(p)] + WLlen[R(p)]);
        WLlen[p] = WLlen[L(p)]; if(WLlen[L(p)] == len(L(p))) WLlen[p] += WLlen[R(p)];
        WRlen[p] = WRlen[R(p)]; if(WRlen[R(p)] == len(R(p))) WRlen[p] += WRlen[L(p)];
    }
    
    void Build(int p, int l, int r) {
        Le[p] = l; Re[p] = r; Lazy[p] = false;
        if(l == r) {
            BTlen[p] = BLlen[p] = BRlen[p] = ((a[l]==1) ? 1 : 0);
            WTlen[p] = WLlen[p] = WRlen[p] = ((a[l]==0) ? 1 : 0);
            return;
        }
        int mid = (l + r) >> 1;
        Build(L(p), l, mid); Build(R(p), mid+1, r);
        Update(p);
    }
    
    int  Query(int p, int l, int r) {
        if(Le[p]==l && Re[p]==r) return BTlen[p];
        Pushdown(p);
        int mid = (Le[p] + Re[p]) >> 1;
        if(r <= mid) return Query(L(p), l, r);
        else if(l > mid) return Query(R(p), l, r);
        else {
            int tmp = max(Query(L(p), l, mid), Query(R(p), mid+1, r));
            tmp = max(tmp, min(mid-l+1, BRlen[L(p)]) + min(r-mid, BLlen[R(p)]));
            return tmp;
        }
    }
    
    void Modify(int p, int l, int r) {
        if(Le[p]==l && Re[p]==r) {
            Lazy[p] ^= true; Update_len(p);
            return;
        }
        Pushdown(p);
        int mid = (Le[p] + Re[p]) >> 1;
        if(r <= mid) Modify(L(p), l, r);
        else if(l > mid) Modify(R(p), l, r);
        else { Modify(L(p), l, mid); Modify(R(p), mid+1, r); }
        Update(p);
    }
    
} T;

int main() {

    while(scanf("%d", &n) != EOF) {
        for(int i=1; i<=n; i++) a[i] = read();
        T.Build(1, 1, n);
        m = read();
        while(m--) {
            int opt=read(), l=read(), r=read();
            if(opt == 0) printf("%d\n", T.Query(1, l, r));
            else T.Modify(1, l, r);
        }
    }
    
    return 0;
}