UVa 12436 Rip Van Winkle's Code 线段树

来源:互联网 发布:php 遍历对象数据 编辑:程序博客网 时间:2024/05/23 23:11

D

Rip Van Winkle's Code

Rip Van Winkle was fed up with everything exceptprogramming. One day he found a problem which required to perform three typesof update operations(A, B, C), and one query operation S over anarraydata[]. Initially all elements of data are equal to 0. Though RipVan Winkle is going to sleep for 20 years, and his code is also super slow, youneed to perform the same update operations and output the result for the queryoperationS in an efficient way.

long long data[250001];

void A( int st, int nd ) {
    for( int i = st; i <= nd; i++ ) data[i] = data[i] + (i - st + 1);
}
void B( int st, int nd ) {
    for( int i = st; i <= nd; i++ ) data[i] = data[i] + (nd - i + 1);
}
void C( int st, int nd, int x ) {
    for( int i = st; i <= nd; i++ ) data[i] = x;
}
long long S( int st, int nd ) {
    long long res = 0;
    for( int i = st; i <= nd; i++ ) res += data[i];
    return res;
}

Input

The first line of input will contain T (≤ 4*105)denoting the number of operations. Each of the nextT lines starts witha character ('A', 'B', 'C' or 'S'), which indicates the type ofoperation. Character'A', 'B' or 'S' will be followed by two integers,st andnd in the same line. Character 'C' is followed by threeintegers,st, nd and x. It's assumed that, 1 ≤ st ≤nd ≤ 250000 and-105 ≤ x ≤ 105.The meanings of these integers are explained by the code of Rip Van Winkle.

Output

For each line starting with the character 'S', print S(st, nd ) as defined in the code. Dataset is huge, so use faster I/O methods.

Sample Input

Output for Sample Input

7
A 1 4
B 2 3
S 1 3
C 3 4 -2
S 2 4
B 1 3
S 2 4
9
0
3

Problem Setter: Anindya Das, Special Thanks: Tanaeem MMoosa, Jane Alam Jan


传送门:UVa 12436 Rip Van Winkle's Code


题目大意:

给你不超过400000次操作,操作区间范围为[1,250000],每次操作可以为:

1.A L R 表示[L,R]中从i=L开始,每个数依次增加i-L+1直到i=R。

2.B L R 表示[L,R]中从i=L开始,每个数依次增加R-i+1直到i=R。

3.C L R V 表示将[L,R]内的数全部设为V。

4.S L R 查询[L,R]内的数之和。


题目分析:

维护三个lazy标记即可。一个增量从左递增增加值的标记,一个增量从左递减增加值的标记,一个改变值的标记。

注意计算上仔细处理以及可能爆int的地方。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define clear( A , X ) memset ( A , X , sizeof A )#define lson l , m , o << 1#define rson m + 1 , r , o << 1 | 1typedef long long Int ;const int maxN = 1000005 ;Int lazyA[maxN] , lazyB[maxN] , lazyC[maxN] ;Int chanA[maxN] , chanB[maxN] , chanC[maxN] ;Int sum[maxN] ;/*chanA:add low to highchanB:add high to lowchanC:set*/void Build () {clear ( lazyA , 0 ) ;clear ( lazyB , 0 ) ;clear ( lazyC , 0 ) ;clear ( chanA , 0 ) ;clear ( chanB , 0 ) ;clear ( chanC , 0 ) ;clear ( sum , 0 ) ;}void PushUp ( int o ) {sum[o] = sum[o << 1] + sum[o << 1 | 1] ;}void PushDown ( int o , int l , int r ) {int m = ( l + r ) >> 1 ;if ( lazyC[o] ) {chanA[o << 1] = chanA[o << 1 | 1] = 0 ;lazyA[o << 1] = lazyA[o << 1 | 1] = 0 ;chanB[o << 1] = chanB[o << 1 | 1] = 0 ;lazyB[o << 1] = lazyB[o << 1 | 1] = 0 ;lazyC[o << 1] = lazyC[o << 1 | 1] = lazyC[o] ;chanC[o << 1] = chanC[o << 1 | 1] = chanC[o] ;sum[o << 1] = chanC[o] * ( m - l + 1 ) ;sum[o << 1 | 1] = chanC[o] * ( r - m ) ;lazyC[o] = 0 ;chanC[o] = 0 ;}if ( lazyA[o] ) {lazyA[o << 1] += lazyA[o] ;chanA[o << 1] += chanA[o] ;lazyA[o << 1 | 1] += lazyA[o] ;chanA[o << 1 | 1] += chanA[o] + lazyA[o] * ( m - l + 1 ) ;sum[o << 1] += ( 2 * chanA[o] + lazyA[o] * ( m - l ) ) * ( m - l + 1 ) / 2 ;sum[o << 1 | 1] += ( 2 * chanA[o] + lazyA[o] * ( r + m - 2 * l + 1 ) ) * ( r - m ) / 2 ;lazyA[o] = 0 ;chanA[o] = 0 ;}if ( lazyB[o] ) {lazyB[o << 1] += lazyB[o] ;chanB[o << 1] += chanB[o] ;lazyB[o << 1 | 1] += lazyB[o] ;chanB[o << 1 | 1] += chanB[o] - lazyB[o] * ( m - l + 1 ) ;sum[o << 1] += ( 2 * chanB[o] - lazyB[o] * ( m - l ) ) * ( m - l + 1 ) / 2 ;sum[o << 1 | 1] += ( 2 * chanB[o] - lazyB[o] * ( r + m - 2 * l + 1 ) ) * ( r - m ) / 2 ;lazyB[o] = 0 ;chanB[o] = 0 ;}}void Update ( int ch , int v , int L , int R , int l , int r , int o ) {if ( L <= l && r <= R ) {if ( 1 == ch ) {++ lazyA[o] ;chanA[o] += l - L + 1 ;sum[o] += (Int) ( l + r + 2 - 2 * L ) * ( r - l + 1 ) / 2 ;}if ( 2 == ch ) {++ lazyB[o] ;chanB[o] += R - l + 1 ;sum[o] += (Int) ( 2 * R + 2 - l - r ) * ( r - l + 1 ) / 2 ;}if ( 3 == ch ) {lazyC[o] = 1 ;lazyA[o] = lazyB[o] = 0 ;chanA[o] = chanB[o] = 0 ;chanC[o] = v ;sum[o] = (Int) v * ( r - l + 1 ) ;}return ;}PushDown ( o , l , r ) ;int m = ( l + r ) >> 1 ;if ( L <= m ) Update ( ch , v , L , R , lson ) ;if ( m <  R ) Update ( ch , v , L , R , rson ) ;PushUp ( o ) ;}Int Query ( int L , int R , int l , int r , int o ) {if ( L <= l && r <= R ) return sum[o] ;PushDown ( o , l , r ) ;int m = ( l + r ) >> 1 ;Int ans = 0 ;if ( L <= m ) ans += Query ( L , R , lson ) ;if ( m <  R ) ans += Query ( L , R , rson ) ;return ans ;}void work () {int n , l , r , v ;char ch ;while ( ~scanf ( "%d" , &n ) ) {Build () ;while ( n -- ) {getchar () ;ch = getchar () ;if ( 'A' == ch ) {scanf ( "%d%d" , &l , &r ) ;Update ( 1 , 0 , l , r , 1 , 250000 , 1 ) ;}if ( 'B' == ch ) {scanf ( "%d%d" , &l , &r ) ;Update ( 2 , 0 , l , r , 1 , 250000 , 1 ) ;}if ( 'C' == ch ) {scanf ( "%d%d%d" , &l , &r , &v ) ;Update ( 3 , v , l , r , 1 , 250000 , 1 ) ;}if ( 'S' == ch ) {scanf ( "%d%d" , &l , &r ) ;Int an = Query ( l , r , 1 , 250000 , 1 ) ;printf ( "%lld\n" , an ) ;}}}}int main () {work () ;return 0 ;}


0 0
原创粉丝点击