题意 :N个数Q条命令,Q a b代表输入Aa, Aa+1, ... , Ab的和。C a b c代表让你把c加给Aa, Aa+1, ... , Ab的每一个数。
思路 :这个题分类好像不是线段树。。不过我硬是按线段树的方法做了,总觉得和HDU1166和1754差不多,反正要注意数据范围很大不能用int,我还因为用了intWA了一次。反正比平时那些模板的更新啊加减什么的都比较麻烦。
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; const int maxn = 5000004 ; typedef long long LL; struct node { int l,r ; LL sum,add ; int boundary ; } Node[maxn] ; int a[maxn] ; void build(int v,int l,int r) { Node[v].l = l ; Node[v].r = r ; Node[v].boundary = (l+r)/2 ; Node[v].add = 0 ; if(l == r) { Node[v].sum = a[l] ; return ; } int mid = (l+r)>>1 ; build(v*2,l,mid) ; build(v*2+1,mid+1,r) ; Node[v].sum = Node[v*2].sum + Node[v*2+1].sum ; } void update(int v,int value,int l,int r) { if(Node[v].l == l && Node[v].r == r) { Node[v].add += value ; return ; } Node[v].sum += (LL)(value*(1+r-l)) ; if(Node[v].boundary >= r) update(v*2,value,l,r) ; else if(Node[v].boundary < l) update(v*2+1,value,l,r) ; else { update(v*2,value,l,Node[v].boundary) ; update(v*2+1,value,Node[v].boundary+1,r) ; } } LL query(int v,int l,int r) { if(Node[v].l == l && Node[v].r == r) { return Node[v].sum + Node[v].add*(LL)(r-l+1) ; } if(Node[v].add != 0) { Node[v*2].add += Node[v].add ; Node[v*2+1].add += Node[v].add ; Node[v].sum += (LL)(Node[v].r-Node[v].l+1)*Node[v].add ; Node[v].add = 0 ; } if(Node[v].boundary >= r) return query(v*2,l,r) ; else if(Node[v].boundary < l) return query(v*2+1,l,r) ; else return query(v*2,l,Node[v].boundary)+query(v*2+1,Node[v].boundary+1,r) ; } int main() { int m,n ; while(~scanf("%d %d",&n,&m)) { for(int i = 1 ; i <= n ; i++ ) { scanf("%d",&a[i]) ; } int x,y,z ; build(1,1,n) ; char str[54] ; for(int i = 1 ; i <= m ; i++) { scanf("%s",str) ; if(str[0] == 'Q') { scanf("%d %d",&x,&y) ; printf("%lld\n",query(1,x,y)) ; } if(str[0] == 'C') { scanf("%d %d %d",&x,&y,&z) ; update(1,z,x,y) ; } } } return 0; }