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 anarray data[]. 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 queryoperation S 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;
}
The first line of input will contain T (≤ 4*105)denoting the number of operations. Each of the next T 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 and nd 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.
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 | 1 typedef 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 high chanB:add high to low chanC: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 ; }