zoukankan      html  css  js  c++  java
  • BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )

    线段树..

    打个 mul , add 的标记就好了..

    这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. 

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

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<vector>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
    #define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
    #define L( x ) ( x << 1 )
    #define R( x ) ( L( x ) ^ 1 )
    #define mid( l , r ) ( ( l + r ) >> 1 )
    #define LC( x ) tree[ L( x ) ]
    #define RC( x ) tree[ R( x ) ]
     
    using namespace std;
     
    const int maxn = 100000 + 5;
     
    int mod;
     
    struct Node {
    int l , r , mul , add , sum;
    Node() : mul( 1 ) , add( 0 ) {} 
    };
     
    Node tree[ maxn << 2 ];
     
    void pushdown( int x ) {
    Node &o = tree[ x ];
    if( o.mul >= 0 ) {
    LC( x ).mul = 1LL * o.mul * LC( x ).mul % mod;
    RC( x ).mul = 1LL * o.mul * RC( x ).mul % mod;
    LC( x ).add = 1LL * LC( x ).add * o.mul % mod;
    RC( x ).add = 1LL * RC( x ).add * o.mul % mod;
    o.mul = 1;
    }
    if( o.add ) {
    LC( x ).add = ( LC( x ).add + o.add ) % mod;
    RC( x ).add = ( RC( x ).add + o.add ) % mod;
    o.add = 0;
    }
    }
     
    void maintain( int x ) {
    Node &o = tree[ x ];
    if( o.r > o.l )
       o.sum = LC( x ).sum + RC( x ).sum;
    o.sum = ( 1LL * o.sum * o.mul + 1LL * o.add * ( o.r - o.l + 1 ) ) % mod;
    if( o.l == o.r ) 
       o.mul = 1 , o.add = 0;
    }
     
    int L , R , v , op;
     
    void update( int x ) {
    Node &o = tree[ x ];
    if( L <= o.l && o.r <= R ) {
    if( op == 1 ) {
       o.mul = 1LL * o.mul * v % mod;
       o.add = 1LL * o.add * v % mod;
    } else 
       o.add = ( o.add + v ) % mod;
    } else {
    pushdown( x );
    int m = mid( o.l , o.r );
    if( L <= m ) update( L( x ) ); else maintain( L( x ) );
    if( m < R ) update( R( x ) ); else maintain( R( x ) );
    }
    maintain( x );
    }    
     
    int query( int x ) {
    Node &o = tree[ x ];
    if( L <= o.l && o.r <= R )
       return o.sum;
    int m = mid( o.l , o.r );
    int ans = 0;
    pushdown( x );
    maintain( L( x ) );
    maintain( R( x ) );
    if( L <= m ) ans = query( L( x ) );
    if( m < R ) ans += query( R( x ) );
    return ans % mod;
    }
     
    int seq[ maxn ];
     
    void build( int x , int l , int r ) {
    Node &o = tree[ x ];
    o.l = l , o.r = r;
    if( l == r ) {
    o.sum = seq[ l ];
    return;
    }
    int m = mid( l , r );
    build( L( x ) , l , m );
    build( R( x ) , m + 1 , r );
    maintain( x );
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    int n;
    cin >> n >> mod;
    Rep( i , n )
       scanf( "%d" , seq + i );
       
    build( 1 , 1 , n );
    int m;
    cin >> m;
    while( m-- ) {
    scanf( "%d%d%d" , &op , &L , &R );
    if( op == 3 ) printf( "%d " , query( 1 ) );
       else {
    scanf( "%d" , &v );
    update( 1 );
    }
    }
    return 0;
    }

      

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

    1798: [Ahoi2009]Seq 维护序列seq

    Time Limit: 30 Sec  Memory Limit: 64 MB
    Submit: 3347  Solved: 1240
    [Submit][Status][Discuss]

    Description

    老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

    Input

    第一行两个整数N和P(1≤P≤1000000000)。第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。第三行有一个整数M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    Output

    对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

    Sample Input

    7 43
    1 2 3 4 5 6 7
    5
    1 2 5 5
    3 2 4
    2 3 7 9
    3 1 3
    3 4 7

    Sample Output

    2
    35
    8

    HINT

    【样例说明】

    初始时数列为(1,2,3,4,5,6,7)。
    经过第1次操作后,数列为(1,10,15,20,25,6,7)。
    对第2次操作,和为10+15+20=45,模43的结果是2。
    经过第3次操作后,数列为(1,10,24,29,34,15,16}
    对第4次操作,和为1+10+24=35,模43的结果是35。
    对第5次操作,和为29+34+15+16=94,模43的结果是8。



    测试数据规模如下表所示

    数据编号 1 2 3 4 5 6 7 8 9 10
    N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
    M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

    Source

  • 相关阅读:
    FlipReverseRotate Lab Report
    各种 LCD GDRAM 格式
    Stellaris Graphics Library : Image Format
    C语言宏 ## __VA_ARGS__
    Clipboard with Custom Clipboard Formats Delphi
    FTDI EEPROM
    SBFX 和 UBFX 有符号和无符号位域提取 BFC 和 BFI 位域清零和位域插入
    防止程序重复执行 Controling the number of application instances
    NAND Flash Page Read Command and Address
    Most Recently Used (MRU) menu component
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4568773.html
Copyright © 2011-2022 走看看