zoukankan      html  css  js  c++  java
  • hdu 3397 Sequence operation (线段树 区间合并 多重标记)

    链接;http://acm.hdu.edu.cn/showproblem.php?pid=3397

    题意:

    给你一串01串,有5种操作

    0. 区间全部变为0

    1.区间全部变为1

    2.区间异或

    3.询问区间1的个数

    4.询问区间被最长连续1的长度

    思路:

    这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表示区间更新值和区间异或,那么向下更新的时候如果如果有same标记,清空当前区间的rev标记,简单维护下就好了,如果有rev标记,且有same标记,那么直接对same异或维护,如果没有same标记那么就维护下区间异或就好了。

    写的超爽,一遍就a了,美滋滋,还以为又要找好久的错。。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    #define ll long long
    
    const int M = 1e5 + 10;
    int lsum1[M<<2],rsum1[M<<2],sum1[M<<2];
    int lsum0[M<<2],rsum0[M<<2],sum0[M<<2];
    int sum[M<<2],same[M<<2],rev[M<<2];
    int a[M];
    
    void pushup(int l,int r,int rt){   
        mid;
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        lsum0[rt] = lsum0[rt<<1]; lsum1[rt] = lsum1[rt<<1];
        rsum0[rt] = rsum0[rt<<1|1]; rsum1[rt] = rsum1[rt<<1|1];
        if(lsum0[rt] == m-l+1) lsum0[rt] += lsum0[rt<<1|1];
        if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<1];
        if(lsum1[rt] == m-l+1) lsum1[rt] += lsum1[rt<<1|1];
        if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<1];
        sum0[rt] = max(max(sum0[rt<<1],sum0[rt<<1|1]),lsum0[rt<<1|1]+rsum0[rt<<1]);
        sum1[rt] = max(max(sum1[rt<<1],sum1[rt<<1|1]),lsum1[rt<<1|1]+rsum1[rt<<1]);
    }
    
    void swa(int len,int rt){
        sum[rt] = len - sum[rt];
        swap(lsum1[rt],lsum0[rt]);
        swap(rsum1[rt],rsum0[rt]);
        swap(sum1[rt],sum0[rt]);
    }
    
    void pushdown(int l,int r,int rt){
        mid;
        if(same[rt]!=-1){
            rev[rt<<1] = rev[rt<<1|1] = 0;
            same[rt<<1] = same[rt<<1|1] = same[rt];
            if(same[rt]){
                sum[rt<<1] = lsum1[rt<<1] = rsum1[rt<<1] = sum1[rt<<1] = m-l+1;
                sum[rt<<1|1] = lsum1[rt<<1|1] = rsum1[rt<<1|1] = sum1[rt<<1|1] = r-m;
                lsum0[rt<<1] = rsum0[rt<<1] = sum0[rt<<1] = sum0[rt<<1|1] = rsum0[rt<<1|1] = lsum0[rt<<1|1] = 0;
            }
            else{
                sum[rt<<1] = lsum1[rt<<1] = rsum1[rt<<1] = sum1[rt<<1] = 0;
                sum[rt<<1|1] = lsum1[rt<<1|1] = rsum1[rt<<1|1] = sum1[rt<<1|1] = 0;
                lsum0[rt<<1] = rsum0[rt<<1] = sum0[rt<<1] = m-l+1;
                sum0[rt<<1|1] = rsum0[rt<<1|1] = lsum0[rt<<1|1] = r-m;
            }
            same[rt] = -1;
        }
        if(rev[rt]){
            if(same[rt<<1] != -1){
                same[rt<<1] ^= 1;
                if(same[rt<<1]){
                    sum[rt<<1] = lsum1[rt<<1] = rsum1[rt<<1] = sum1[rt<<1] = m-l+1;
                    lsum0[rt<<1] = rsum0[rt<<1] = sum0[rt<<1] = 0;
                }
                else{
                    sum[rt<<1] = lsum1[rt<<1] = rsum1[rt<<1] = sum1[rt<<1] = 0;
                    lsum0[rt<<1] = rsum0[rt<<1] = sum0[rt<<1] = m-l+1;
                }
            }
            else{
                rev[rt<<1] ^= 1;
                swa(m-l+1,rt<<1);
            }
            if(same[rt<<1|1] != -1){
                same[rt<<1|1] ^= 1;
                if(same[rt<<1|1]){
                    sum[rt<<1|1] = lsum1[rt<<1|1] = rsum1[rt<<1|1] = sum1[rt<<1|1] = r-m;
                    sum0[rt<<1|1] = rsum0[rt<<1|1] = lsum0[rt<<1|1] = 0;
                }
                else{
                    sum[rt<<1|1] = lsum1[rt<<1|1] = rsum1[rt<<1|1] = sum1[rt<<1|1] = 0;
                    sum0[rt<<1|1] = rsum0[rt<<1|1] = lsum0[rt<<1|1] = r-m;
                }
            }
            else{
                rev[rt<<1|1] ^= 1;
                swa(r-m,rt<<1|1);
            }
            rev[rt] = 0;
        }
    }
    
    void build(int l,int r,int rt){
        same[rt] = -1; rev[rt] = 0;
        lsum1[rt] = rsum1[rt] = lsum0[rt] = rsum0[rt] = sum0[rt] = sum1[rt] = sum[rt] = 0;
        if(l == r){
            if(a[l]){
                lsum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = 1;
                lsum0[rt] = rsum0[rt] = sum0[rt] = 0;
            }
            else {
                sum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = 0;
                lsum0[rt] = rsum0[rt] = sum0[rt] = 1;
            }
            return ;
        }
        mid ;
        build(lson); build(rson);
        pushup(l,r,rt);
    }
    
    void update_same(int L,int R,int c,int l,int r,int rt){
        if(L <= l&&R >= r){
            rev[rt] = 0;
            same[rt] = c;
            if(same[rt]){
                sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+1;
                lsum0[rt] = rsum0[rt] = sum0[rt] = 0;
            }
            else{
                sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = 0;
                lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+1;
            }
            return ;
        }
        pushdown(l,r,rt);
        mid;
        if(L <= m) update_same(L,R,c,lson);
        if(R > m) update_same(L,R,c,rson);
        pushup(l,r,rt);
    }
    
    void update_rev(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            if(same[rt] != -1){
                same[rt] ^= 1;
                if(same[rt]){
                    sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+1;
                    lsum0[rt] = rsum0[rt] = sum0[rt] = 0;
                }
                else{
                    sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = 0;
                    lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+1;
                }
            }
            else{
                rev[rt] ^= 1;
                swa(r-l+1,rt);
            }
            return ;
        }
        mid ;
        pushdown(l,r,rt);
        if(L <= m) update_rev(L,R,lson);
        if(R > m) update_rev(L,R,rson);
        pushup(l,r,rt);
    }
    
    int query_sum(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        pushdown(l,r,rt);
        mid;
        int ret = 0;
        if(L <= m) ret += query_sum(L,R,lson);
        if(R > m) ret += query_sum(L,R,rson);
        return ret;
    }
    
    int query_max(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            return sum1[rt];
        }
        pushdown(l,r,rt);
        mid;
        int ret = 0;
        if(L > m) return query_max(L,R,rson);
        if(R <= m) return query_max(L,R,lson);
        int t1 = query_max(L,R,lson);
        int t2 = query_max(L,R,rson);
        int ls = min(rsum1[rt<<1],m-L+1);
        int rs = min(lsum1[rt<<1|1],R-m);
        return max(max(t1,t2),ls+rs);
    }
    
    int main()
    {
        int n,q,x,y,op,t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&q);
            for(int i = 1;i <= n;i ++)
                scanf("%d",&a[i]);
            build(1,n,1);
            while(q--){
                scanf("%d%d%d",&op,&x,&y);
                x++; y++;
                if(op == 0){
                    update_same(x,y,0,1,n,1);
                }
                else if(op == 1){
                    update_same(x,y,1,1,n,1);
                }
                else if(op == 2){
                    update_rev(x,y,1,n,1);
                }
                else if(op == 3){
                    printf("%d
    ",query_sum(x,y,1,n,1));
                }
                else {
                    printf("%d
    ",query_max(x,y,1,n,1));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    mongodb3.6 query plan机制变更导致慢查询问题排查
    zoj 3822 概率期望dp入门
    poj 4513 吉哥系列故事――完美队形II 最长回文子串
    poj 3974 Palindrome O(n)回文子串(Manacher)算法
    hdu 4405 Aeroplane chess 概率dp入门题
    hdu 5001 walk 概率dp入门题
    hdu 3586 Information Disturbing 树形dp+二分
    hdu 2296 Ring AC自动机+DP
    poj 3691 DNA repair AC自动机+DP
    hdu 1520 Anniversary party 树形dp水题
  • 原文地址:https://www.cnblogs.com/kls123/p/9781070.html
Copyright © 2011-2022 走看看