http://poj.org/problem?id=3468 题目链接, 很经典的线段树的应用, 这里复习一下, 再写一遍, 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100000 + 10; int N, Q; int a[maxn]; struct Segment{ int l, r; long long sum; int lazy; }seg[3*maxn]; void build(int rt, int l, int r){ seg[rt].l = l; seg[rt].r = r; seg[rt].lazy = 0; if(l==r){ seg[rt].sum = a[l]; return ; } int chl = 2*rt, chr = 2*rt+1; int mid = (l+r)/2; build(chl, l, mid); build(chr, mid+1, r); seg[rt].sum = seg[chl].sum + seg[chr].sum; } void push_down(int rt){ int chl = 2*rt, chr = 2*rt+1; if(seg[rt].lazy){ seg[chl].sum += (long long)seg[rt].lazy*(long long)(seg[chl].r-seg[chl].l+1); seg[chl].lazy += seg[rt].lazy; seg[chr].sum += (long long)seg[rt].lazy*(long long)(seg[chr].r-seg[chr].l+1); seg[chr].lazy += seg[rt].lazy; seg[rt].lazy = 0; } } void update(int rt, int l, int r, int c){ if(seg[rt].l==l && seg[rt].r==r){ seg[rt].sum += (long long)c*(r-l+1); seg[rt].lazy += c; return ; } push_down(rt); int mid = (seg[rt].l+seg[rt].r)/2; if(r <= mid) update(2*rt, l, r, c); else if(l>mid) update(2*rt+1, l, r, c); else{ update(2*rt, l, mid, c); update(2*rt+1, mid+1, r, c); } seg[rt].sum = seg[2*rt].sum + seg[2*rt+1].sum; } long long query(int rt, int l, int r){ if(seg[rt].l==l && seg[rt].r==r){ return seg[rt].sum; } push_down(rt); int mid = (seg[rt].l+seg[rt].r)/2; if(r <= mid) return query(2*rt, l, r); else if(l > mid) return query(2*rt+1, l, r); else { long long v1 = query(2*rt, l, mid); long long v2 = query(2*rt+1, mid+1, r); return v1 + v2; } seg[rt].sum = seg[2*rt].sum + seg[2*rt+1].sum; } int main() { scanf("%d%d", &N, &Q); for(int i=1; i<=N; i++) scanf("%d", &a[i]); build(1, 1, N); for(int i=0; i<Q; i++){ char s[6]; scanf("%s", s); if(s[0] == ‘Q‘){ int l, r; scanf("%d%d", &l, &r); printf("%lld\n", query(1, l, r)); }else{ int l, r, c; scanf("%d%d%d", &l, &r, &c); update(1, l, r, c); } } return 0; }
时间: 2024-10-17 17:43:12