题目链接: http://poj.org/problem?id=3468
题目描述: 一组数列, 可进行一段区间加上某一个数, 和区间查询
解题思路: 线段树, 之前的那道题是求总区间直接输出sum[1] 就可以了, 这次有了区间查询, 同理, 查询的时候Pushdown
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 typedef long long LL; using namespace std; int cases; const int maxn = 1e5+100; int n; int q; LL sum[maxn<<2]; LL add[maxn<<2]; char op[4]; void pushUp( int rt ) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void pushDown( int rt, int x ) { if( add[rt] ) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += (x - (x>>1)) * add[rt]; sum[rt<<1|1] += (x>>1) * add[rt]; add[rt] = 0; } } void upDate( int L, int R, int x, int l, int r, int rt ) { if( L <= l && r <= R ) { add[rt] += x; sum[rt] += (LL)(r - l + 1) * x; return; } pushDown( rt, r - l + 1 ); int m = (l + r) >> 1; if( L <= m ) upDate(L, R, x, lson); if( R > m ) upDate(L, R, x, rson); pushUp(rt); } void build( int l, int r, int rt ) { add[rt] = 0; if( l == r ) { scanf( "%lld", &sum[rt] ); return; } int m = (l + r) >> 1; build( lson ); build( rson ); pushUp( rt ); return; } LL Query( int L, int R, int l, int r, int rt ) { if( L <= l && r <= R ) { return sum[rt]; } pushDown(rt, r - l + 1); LL ret = 0; int m = (l + r) >> 1; if( L <= m ) ret += Query( L, R, lson ); if( R > m ) ret += Query( L, R, rson ); return ret; } int main() { while( scanf( "%d%d", &n, &q ) == 2 ) { build( 1, n, 1 ); while( q-- ) { scanf( "%s", op ); if( op[0] == 'C' ) { int a, b, c; scanf( "%d%d%d", &a, &b, &c ); upDate( a, b, c, 1, n, 1 ); } else { int a, b; scanf( "%d%d", &a, &b ); printf( "%lld ", Query( a, b, 1, n , 1) ); } } } return 0; }
思考: 本身题没啥可说的, 和上道题很类似, 但是我在pushdown函数中sum[rt] ..... 应该是加等于的, 我写成了 等于所以一直卡在那里半个小时....发现的时候就觉得自己特别蠢。 以后应该仔细一点儿