题目链接:
http://poj.org/problem?id=3468
解题思路:
给出了一个序列,你需要处理如下两种询问。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
典型的线段树区间修改,然后让你求区间和的问题,但是题目有大坑,注意-1000000000≤ Ai ≤1000000000,要用long long型,而
且虽然操作C增加c的范围只有-10000 ≤ c ≤ 10000,但是与它相关的参数都必须也要用long long型。。。注意了这个,剩下的就是
简单的线段树区间修改了。。。
AC代码:
#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const int N = 100005; struct node{ int l,r; ll sum; ll add; }tree[N<<2]; ll a[N]; ll ans; void maintain(int id){ tree[id].sum = tree[id<<1].sum + tree[id<<1|1].sum; } void build(int id,int l,int r){//id:index tree[id].l = l; tree[id].r = r; tree[id].add = 0; if(l == r){ tree[id].sum = a[l]; return; } int mid = (l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); maintain(id); } void pushdown(int id){ if(tree[id].add){ ll tmp = tree[id].add; tree[id<<1].add += tmp;tree[id<<1|1].add += tmp; tree[id<<1].sum += (tree[id<<1].r-tree[id<<1].l+1)*tmp; tree[id<<1|1].sum += (tree[id<<1|1].r - tree[id<<1|1].l+1)*tmp; tree[id].add = 0; } } void update(int id,int l,int r,ll val){ if(tree[id].l >= l && tree[id].r <= r){ tree[id].add += val; tree[id].sum += (tree[id].r-tree[id].l+1)*val; return; } pushdown(id); int mid = (tree[id].l+tree[id].r)>>1; if(l <= mid) update(id<<1,l,r,val); if(mid < r) update((id<<1)+1,l,r,val); maintain(id); } void query(int id,int l,int r){ if(tree[id].l >= l && tree[id].r <= r){ ans += tree[id].sum; return; } pushdown(id); int mid = (tree[id].l+tree[id].r)>>1; if(l <= mid) query(id<<1,l,r); if(mid < r) query(id<<1|1,l,r); maintain(id); } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i = 1; i <= n; i++) scanf("%lld",&a[i]); build(1,1,n); char op[10]; int a,b; ll c; while(m--){ scanf("%s",op); if(op[0] == 'Q'){ scanf("%d%d",&a,&b); ans = 0; query(1,a,b); printf("%lld\n",ans); } else if(op[0] == 'C'){ scanf("%d%d%lld",&a,&b,&c); update(1,a,b,c); } } } return 0; }