zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    希腊字母写法
    The ASP.NET MVC request processing line
    lambda aggregation
    UVA 10763 Foreign Exchange
    UVA 10624 Super Number
    UVA 10041 Vito's Family
    UVA 10340 All in All
    UVA 10026 Shoemaker's Problem
    HDU 3683 Gomoku
    UVA 11210 Chinese Mahjong
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4574998.html
Copyright © 2011-2022 走看看