->题目请戳这里<-
题目大意:红果果的线段树,给n个数,2种操作,Q a b,查询a到b这个区间和,C a b c,a到b区间每个数加上c。
题目分析:线段树维护区间和,要加lazy标记。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 100005; typedef __int64 ll; struct node { int lazy; ll sum,add; }lcm[N<<2]; int m,n; void build(int num,int s,int e) { lcm[num].lazy = 0; lcm[num].sum = lcm[num].add = 0; if(s == e) return; int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); } void insert(int num,int s,int e,int l,int r,int val) { if(s == l && e == r) { lcm[num].lazy = 1; lcm[num].add += val; return; } if(lcm[num].lazy == 1) { lcm[num<<1].lazy = 1; lcm[num<<1|1].lazy = 1; lcm[num<<1].add += lcm[num].add; lcm[num<<1|1].add += lcm[num].add; lcm[num].add = 0; lcm[num].lazy = 0; } int mid = (s + e)>>1; if(r <= mid) { insert(num<<1,s,mid,l,r,val); } else { if(l > mid) insert(num<<1|1,mid + 1,e,l,r,val); else { insert(num<<1,s,mid,l,mid,val); insert(num<<1|1,mid + 1,e,mid + 1,r,val); } } lcm[num].sum = lcm[num<<1].sum + lcm[num<<1|1].sum; lcm[num].sum += lcm[num<<1].add * (mid + 1 - s) + lcm[num<<1|1].add * (e - mid); } ll query(int num,int s,int e,int l,int r) { if(s == l && e == r) { return lcm[num].add * (e - s + 1) + lcm[num].sum; } if(lcm[num].lazy == 1) { lcm[num<<1].lazy = lcm[num<<1|1].lazy = 1; lcm[num<<1].add += lcm[num].add; lcm[num<<1|1].add += lcm[num].add; lcm[num].sum += (e - s + 1) * lcm[num].add; lcm[num].add = 0; lcm[num].lazy = 0; } int mid = (s + e)>>1; if(r <= mid) return query(num<<1,s,mid,l,r); else { if(l > mid) return query(num<<1|1,mid + 1,e,l,r); else { return query(num<<1,s,mid,l,mid) + query(num<<1|1,mid + 1,e,mid + 1,r); } } } int main() { int i; int a,b,c; char op[3]; while(scanf("%d%d",&n,&m) != EOF) { build(1,1,n); for(i = 1;i <= n;i ++) { scanf("%d",&a); insert(1,1,n,i,i,a); } while(m --) { scanf("%s",op); if(op[0] == 'Q') { scanf("%d%d",&a,&b); printf("%I64d\n",query(1,1,n,a,b)); } else { scanf("%d%d%d",&a,&b,&c); insert(1,1,n,a,b,c); } } //printf("%I64d\n",lcm[1].sum); } return 0; } //6332K 1954MS