POJ 3468
经典区间更新题, 第一次完整敲完, 很不熟练, 要好好提升姿势水平。。
AC code:
//lrl's submission #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define debug 0 #define LL long long #define ls root << 1, l, mid #define rs root << 1 | 1, mid + 1, r #define inf 0x3f3f3f3f #define M(a, b) memset(a, b, sizeof(a)) const int maxn = 100000 + 5; int n, m; struct node { LL v; //爆int LL la; } sum[maxn << 2]; void pushDown(int root, int l, int r) //下移lazy { if(sum[root].la){ int mid = (l + r) >> 1; sum[root << 1].la += sum[root].la; sum[root << 1 | 1].la += sum[root].la; sum[root << 1].v += (mid - l + 1) * sum[root].la; //区间加和, 左孩子,右孩子分开处理 sum[root << 1 | 1].v += (r - mid) * sum[root].la; sum[root].la = 0; } } void update(int root, int l, int r, int ul, int ur, int add) //维护 { if(ul > r || ur < l) return; if(ul <= l && ur >= r) { sum[root].v += (r - l + 1) * add; sum[root].la += add; return; } pushDown(root, l, r); //lazy标记下移 int mid = (l + r) >> 1; update(ls, ul, ur, add); update(rs, ul, ur, add); sum[root].v = sum[root << 1].v + sum[root << 1 | 1].v; } void build(int root, int l, int r) //建树 { sum[root].la = 0; if(l == r) { scanf("%I64d", &sum[root].v); return; } int mid = (l + r) >> 1; build(ls); build(rs); sum[root].v = sum[root << 1].v + sum[root << 1 | 1].v; } LL query(int root, int l, int r, int ql, int qr){ //查询 if(ql > r || qr < l) return 0; //无重合, 返回0 if(ql <= l && qr >= r) { return sum[root].v; //查询区间内直接返回节点v } pushDown(root, l, r); int mid = (l + r) >> 1; return query(ls, ql, qr) + query(rs, ql, qr); } int main() { #if debug freopen("in.txt", "r", stdin); #endif // debug char s[10]; int a, b, c; while(~scanf("%d%d", &n, &m)) { M(sum, 0); build(1, 1, n); while(m--) { scanf("%s", s); if(s[0] == 'Q') { scanf("%d%d", &a, &b); printf("%I64d\n", query(1, 1, n, a, b)); } else { scanf("%d%d%d", &a, &b, &c); update(1, 1, n, a, b, c); } } } return 0; }