• BZOJ 1858: [Scoi2010]序列操作( 线段树 )


    略恶心的线段树...不过只要弄清楚了AC应该不难....

    ----------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; i++ )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
    #define L( x ) ( ( x ) << 1 )
    #define R( x ) ( L( x ) ^ 1 )
    #define LC L( x ) , l , m
    #define RC R( x ) , m + 1 , r
    #define X x , l , r
    #define XX int x , int l , int r
    #define M( l , r ) ( ( l + r ) >> 1 )
    #define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
     
    using namespace std;
     
    const int maxn = 100000 + 5;
    const int maxnode = 270000;
     
    int n , seq[ maxn ];
     
    struct Node {
    int sum , l_cnt[ 2 ] , r_cnt[ 2 ] , cnt[ 2 ] , set;
    bool rev;
    Node() {
    set = -1;
    rev = false;
    }
    };
     
    Node tree[ maxnode ];
     
    int L , R , op;
     
    void maintain( XX ) {
    Node &o = tree[ x ];
    if( r > l ) {
    Node &lc = tree[ L( x ) ] , &rc = tree[ R( x ) ];
    int m = M( l , r );
       o.sum = lc.sum + rc.sum;
       rep( i , 2 ) {
           o.cnt[ i ] = max( max( lc.cnt[ i ] , rc.cnt[ i ] ) , lc.r_cnt[ i ] + rc.l_cnt[ i ] );
           if( lc.l_cnt[ i ] == m - l + 1 )
               o.l_cnt[ i ] = lc.l_cnt[ i ] + rc.l_cnt[ i ];
           else
       o.l_cnt[ i ] = lc.l_cnt[ i ];
           if( rc.r_cnt[ i ] == r - m )
               o.r_cnt[ i ] = rc.r_cnt[ i ] + lc.r_cnt[ i ];
           else
       o.r_cnt[ i ] = rc.r_cnt[ i ];
       }
    }
    if( o.set != -1 ) {
    o.sum = o.set ? r - l + 1 : 0;
    o.cnt[ 1 ] = o.l_cnt[ 1 ] = o.r_cnt[ 1 ] = o.sum;
    o.cnt[ 0 ] = o.l_cnt[ 0 ] = o.r_cnt[ 0 ] = r - l + 1 - o.sum;
    }
    if( o.rev ) {
    o.sum = r - l + 1 - o.sum;
    swap( o.l_cnt[ 0 ] , o.l_cnt[ 1 ] );
    swap( o.r_cnt[ 0 ] , o.r_cnt[ 1 ] );
    swap( o.cnt[ 0 ] , o.cnt[ 1 ] );
    }
    }
     
    void pushdown( XX ) {
    Node &o = tree[ x ] , &lc = tree[ L( x ) ] , &rc = tree[ R( x ) ];
    if( o.set != -1 ) {
    lc.set = rc.set = o.set;
    lc.rev = rc.rev = false;
    o.set = -1;
    }
    if( o.rev ) {
    lc.rev ^= 1;
    rc.rev ^= 1;
    o.rev =false;
    }
    }
     
    void update( XX ) {
    Node &o = tree[ x ];
    if( L <= l && r <= R ) {
    if( op == 2 ) {
    if( o.set != -1 ) o.set ^= 1;
       else o.rev ^= 1;
    } else {
       o.set = op;
       o.rev = false;
    }  
    } else {
    int m = M( l , r );
       pushdown( X );
       maintain( LC );
       maintain( RC );
    if( L <= m ) update( LC );
    if( m < R ) update( RC );
    }
    maintain( X );
    }
     
    Node merge( int l , int r , Node lc , Node rc ) {
    Node o;
    int m = M( l , r );
    o.sum = lc.sum + rc.sum;
    rep( i , 2 ) {
       o.cnt[ i ] = max( max( lc.cnt[ i ] , rc.cnt[ i ] ) , lc.r_cnt[ i ] + rc.l_cnt[ i ] );
         if( lc.l_cnt[ i ] == m - l + 1 )
       o.l_cnt[ i ] = lc.l_cnt[ i ] + rc.l_cnt[ i ];
    else
    o.l_cnt[ i ] = lc.l_cnt[ i ];
    if( rc.r_cnt[ i ] == r - m )
       o.r_cnt[ i ] = rc.r_cnt[ i ] + lc.r_cnt[ i ];
    else
    o.r_cnt[ i ] = rc.r_cnt[ i ];
    }
    return o;
    }
     
    Node query( XX ) {
    Node &o = tree[ x ];
    if( L <= l && r <= R )
    return o;
    int m = M( l , r );
    pushdown( X );
    maintain( LC );
    maintain( RC );
    if( R <= m ) return query( LC );
    else if( m < L ) return query( RC );
    else return merge( l , r , query( LC ) , query( RC ) );
     
    void build( XX ) {
    Node &o = tree[ x ];
    if( l == r ) {
    o.set =seq[ l ];
    } else {
    int m = M( l , r );
    build( LC );
    build( RC );
    }
    maintain( X );
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    int m;
    cin >> n >> m;
    Rep( i , n )
       scanf( "%d" , seq + i );
    build( 1 , 1 , n );
        while( m-- ) {
        scanf( "%d%d%d" , &op , &L , &R );
        L++ , R++;
        if( op < 3 ) update( 1 , 1 , n );
         else {
        Node o = query( 1 , 1 , n );
        printf( "%d " , op == 3 ? o.sum : o.cnt[ 1 ] );
        }
     
        }
        
    return 0;
    }

      

    ----------------------------------------------------------------

    1858: [Scoi2010]序列操作

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1425  Solved: 737
    [Submit][Status][Discuss]

    Description

    lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 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 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

    Input

    输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b

    Output

    对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

    Sample Input

    10 10
    0 0 0 1 1 0 1 0 1 1
    1 0 2
    3 0 5
    2 2 2
    4 0 4
    0 3 6
    2 3 7
    4 2 8
    1 0 5
    0 5 6
    3 3 9

    Sample Output

    5
    2
    6
    5

    HINT

    对于30%的数据,1<=n, m<=1000
    对于100%的数据,1<=n, m<=100000

    Source

  • 相关阅读:
    CSS——制作天天生鲜主页
    HTML——制作一个图片列表
    HTML——制作一个简易菜单栏
    CSS——三种页面引入方法
    【20170903】模拟赛
    【LA 3942】 Remember the word
    【BZOJ 1036】 树的统计count
    UVA 12299 RMQ with shifts
    【20170706】次短路
    【20170706】保卫萝卜
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4574998.html
Copyright © 2020-2023  润新知