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;
    }
  • 相关阅读:
    微信小程序HTTPS
    微信商城-1简介
    va_list
    Event log c++ sample.
    EVENT LOGGING
    Analyze Program Runtime Stack
    unknow table alarmtemp error when drop database (mysql)
    This application has request the Runtime to terminate it in an unusual way.
    How to check if Visual Studio 2005 SP1 is installed
    SetUnhandledExceptionFilter
  • 原文地址:https://www.cnblogs.com/kls123/p/9781070.html
Copyright © 2011-2022 走看看