hdu 3397 线段树前后缀blahblah Sequence operation

来源:互联网 发布:算法工程师要求 编辑:程序博客网 时间:2024/06/05 15:21
题意:
给出一个长度为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: 0Sol: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 | 1using 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 ) >> 1int 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);            }        }    }}
原创粉丝点击