hdu 3397 线段树前后缀blahblah Sequence operation

题意:
给出一个长度为N(N <= 100000)的数列,然后是五种操作:
插入操作:
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串

解:

      正解应该比较简单。然而我的解就有点Orz了。 每个节点信息是:

      preb, prew,sufb,sufw,mxb,mxw,sumb,sumw,Xor 这么多。

     其他几个就不用说了,sumb是记录这个区间有多少1,Xor是lazy标志(之前没有这个,果断wa了)。 然后就写得。。。不过还好,push_up没写错呵呵。。。

后续:

      简单的解法就是只维护一个cov就行了。cov = 1/0,表示这个区间全是1或者全是0,cov = -1表示有多种值。Orz。。。。


/*
Pro: 0


Sol:


date:
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#define maxn 100010
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m =(l + r) >> 1
#define lson l,m , rt << 1
#define rson m + 1 , r, rt << 1 | 1
using namespace std;
int preb[maxn << 2], sufb[maxn << 2], prew[maxn << 2], sufw[maxn << 2], mxb[maxn << 2], mxw[maxn << 2];
int sumb[maxn << 2],sumw[maxn << 2], Xor[maxn << 2];
int n,T,Q,tmp,op,a,b;
inline int max(int a, int b, int c){
    return  ( (a > b) ? ( (a > c) ? a: c) : ( (b > c) ? b : c) );
}
void push_up(int rt, int m){
    sumb[rt] = sumb[ls] + sumb[rs];
    sumw[rt] = sumw[ls] + sumw[rs];


    preb[rt] = preb[ls];
    if(preb[ls] == m - (m >> 1)) preb[rt] += preb[rs];
    prew[rt] = prew[ls];
    if(prew[ls] == m - (m >> 1)) prew[rt] += prew[rs];


    sufb[rt] = sufb[rs];
    if(sufb[rs] == (m >> 1)) sufb[rt] += sufb[ls];
    sufw[rt] = sufw[rs];
    if(sufw[rs] == (m >> 1)) sufw[rt] += sufw[ls];


    mxb[rt] = max(mxb[ls], mxb[rs], preb[rs] + sufb[ls]);
    mxw[rt] = max(mxw[ls], mxw[rs], prew[rs] + sufw[ls]);
}
void Exc(int rt){
    swap(preb[rt],prew[rt]);
    swap(sufb[rt],sufw[rt]);
    swap(sumb[rt],sumw[rt]);
    swap(mxb[rt],mxw[rt]);
}
void push_dn(int rt, int m){
    if(Xor[rt]){//异或是lazy,又是必须
        Xor[ls] ^= 1;
        Xor[rs] ^= 1;
        Exc(ls); Exc(rs);
        Xor[rt] = 0;
    }
    if(sumb[rt] == m){
        preb[ls] = sufb[ls] = mxb[ls] = sumb[ls] = m - (m >> 1);
        preb[rs] = sufb[rs] = mxb[rs] = sumb[rs] = (m >> 1);
        prew[ls] = sufw[ls] = mxw[ls] = sumw[ls] = 0;
        prew[rs] = sufw[rs] = mxw[rs] = sumw[rs] = 0;
    }else if(sumw[rt] == m){
        preb[ls] = sufb[ls] = mxb[ls] = sumb[ls] = 0;
        preb[rs] = sufb[rs] = mxb[rs] = sumb[rs] = 0;
        prew[ls] = sufw[ls] = mxw[ls] = sumw[ls] = m - (m >> 1);
        prew[rs] = sufw[rs] = mxw[rs] = sumw[rs] = (m >> 1);
    }
}
void build(int l , int r, int rt){
    Xor[rt] = 0;
    if(l == r) {
        scanf("%d",&tmp);
        if(tmp){
            preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 1;
            prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 0;
        }else{
            preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 0;
            prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 1;
        }
        return ;
    } havem;
    build(lson); build(rson);
    push_up(rt, r - l + 1);
}
void update(int L, int R, int op, int l, int r, int rt){
    if(L <= l && r <= R){
        if(op == 0){
            preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 0;
            prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = r - l + 1;
            return ;
        }else if(op == 1){
            preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = r - l + 1;
            prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 0;
            return;
        }
        Exc(rt); Xor[rt] ^= 1; return ;
    }havem;
    push_dn(rt, r - l + 1);
    if(L <= m) update(L,R,op,lson);
    if(R > m) update(L,R,op,rson);
    push_up(rt,r - l + 1);
}
int query3(int L, int R, int l, int r, int rt){//3 all 1's ; 4 longest 1's
    if(L <= l && r <= R){
            return sumb[rt];
    } havem;
    push_dn(rt, r - l + 1);
    int ret = 0;
    if(L <= m) ret += query3(L,R,lson);
    if(R > m) ret += query3(L,R,rson);
    return ret;
}
int query4(int L, int R, int l, int r, int rt){//3 all 1's ; 4 longest 1's
    if(L <= l && r <= R){
        return mxb[rt];
    } havem;
    push_dn(rt, r - l + 1);
    if(R <= m) return query4(L,R,lson);
    if(L > m) return query4(L,R,rson);
    int ret = max(query4(L,R,lson), query4(L,R,rson));
    ret = max(ret, min(m - L + 1, sufb[ls]) + min(R - m, preb[rs])  );
    return ret;
}
int main(){
    scanf("%d",&T);
    while(T --){
        scanf("%d%d",&n,&Q);
        build(0,n - 1,1);//
        for(int i = 0; i < Q; i ++){
            scanf("%d%d%d",&op,&a,&b);
            if(op == 0){
                update(a,b,op,0,n - 1,1);//期间全变为0
            }else if(op == 1){
                update(a,b,op,0,n - 1,1);//期间全变为1
            }else if(op == 2){
                update(a,b,op,0,n - 1,1);//期间0,1互换
            }else if(op == 3){
                printf("%d\n",query3(a,b,0,n - 1,1) );//all 1's in [a,b]
            }else{
                printf("%d\n",query4(a,b,0,n - 1,1) );//longest 1's in [a,b]
            }
        }
    }
	return 0;
}
#include <cstdio>
using namespace std;
#define maxn 100010
#define lson l, m , rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m = (l + r ) >> 1
int n,Q,a,b,T;
//首先得声明,cov不是lazy标志,不然是不会出现在push_up里面的
int cov[maxn << 2],ri, max_len,cur_len;
void push_up(int rt){
    if(cov[ls] == cov[rs])//cov 可以为-1
        cov[rt] = cov[ls];
    else
        cov[rt] = -1;
}
void build(int l , int r, int rt){
    if(l == r){
        scanf("%d",&cov[rt]);
        return ;
    }havem;
    build(lson); build(rson);
    push_up(rt);
}
void push_dn(int rt){
    if(cov[rt] >= 0){
        cov[ls] = cov[rs] = cov[rt];
        cov[rt] = -1;
    }
}
void update(int L, int R, int val, int l, int r, int rt){
    if(cov[rt] == val)
        return ;
    if(L <= l && r <= R){
        cov[rt] = val;
        return;
    }push_dn(rt);
    havem;
    if(L <= m) update(L,R,val,lson);
    if(R > m) update(L,R,val,rson);
    push_up(rt);
}
void update_xor(int L,int R, int l, int r, int rt){
    if(L <= l && r <= R && cov[rt] >= 0){
        cov[rt] ^= 1;
        return ;
    }push_dn(rt);
    havem;
    if(L <= m) update_xor(L,R,lson);
    if(R > m) update_xor(L,R,rson);
    push_up(rt);
}
int query(int L, int R, int l, int r, int rt){
    if(L <= l && r <= R){
        if(cov[rt] == 0){
            return 0;
        }
        if(cov[rt] == 1){
            return r - l + 1;
        }
    }
    havem; push_dn(rt);
    if(R <= m)
        return query(L , R, lson);
    if(L > m)
        return  query(L,R,rson);
    return query(L , R , lson) + query(L,R,rson);
}
void queryl(int L,int R, int l, int r, int rt){
    if(cov[rt] == 0)
        return ;
    if(L <= l && r <= R && cov[rt] == 1){
        if(L == ri + 1) //现在这个区间如果接着上个区间
            cur_len += r - l + 1;
        else
            cur_len = r - l + 1;
        if(cur_len > max_len)
            max_len = cur_len;
        ri = r;
        return ;
    }push_dn(rt); havem;
    if(R <= m)
         queryl(L , R, lson);
    else if(L > m)
         queryl(L,R,rson);
    else//这里是m和m + 1, 这里我wa了很久,这跟上面的L == ri + 1有关
         queryl(L , m , lson),    queryl( m + 1 ,R,rson);
}
int main(){
    scanf("%d",&T);
    int op,a,b;
    while(T --){
        scanf("%d%d",&n,&Q);
        build(1,n,1);
        while(Q --){
            scanf("%d%d%d",&op,&a,&b); a ++, b ++;
            switch(op){
                case 0 :
                    update(a,b,0,1,n,1);
                    break;
                case 1:
                    update(a,b,1,1,n,1);
                    break;
                case 2:
                    update_xor(a,b,1,n,1);
                    break;
                case 3:
                    printf("%d\n",query(a,b,1,n,1) );
                    break;
                case 4:
                    max_len = cur_len = 0;
                    ri = 0;
                    queryl(a,b,1, n, 1);
                    printf("%d\n",max_len);
            }
        }
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值