题目链接:Click here~~
题意:
给你n个数,然后有两种操作,求某段区间的和 or 将某段区间元素加若干值。
解题思路:
线段树。。。模仿别人的。1516MS。
貌似zkw式线段树1329MS,两个树状数组可以做到1047MS,等以后再学,TAT。
#include <stdio.h> #define L(x) (x<<1) #define R(x) (x<<1|1) #define MID(x,y) ((x+y)>>1) typedef __int64 LL; const int M = 100003; int v[M]; struct Tnode { int l,r; LL sum,delta; //sum记录区间和、delta记录区间的公共增量 }T[M<<2]; void Build(int u,int l,int r) { T[u].l = l , T[u].r = r; if(l == r-1) { T[u].sum = v[l]; T[u].delta = 0; return ; } int mid = MID(l,r); Build(L(u),l,mid); Build(R(u),mid,r); T[u].sum = T[L(u)].sum + T[R(u)].sum; T[u].delta = 0; } void Updata(int u,int l,int r,LL up) { if(T[u].l == l && T[u].r == r) { T[u].delta += up; return ; } else T[u].sum += up*(r-l); int mid = MID(T[u].l,T[u].r); if(l >= mid) Updata(R(u),l,r,up); else if(r <= mid) Updata(L(u),l,r,up); else { Updata(L(u),l,mid,up); Updata(R(u),mid,r,up); } } LL Query(int u,int l,int r) { LL delta = T[u].delta; if(T[u].l == l && T[u].r == r) return T[u].sum + delta*(r-l); T[L(u)].delta += delta; T[R(u)].delta += delta; T[u].sum += delta*(T[u].r-T[u].l); T[u].delta = 0; int mid = MID(T[u].l,T[u].r); if(l >= mid) return Query(R(u),l,r); else if(r <= mid) return Query(L(u),l,r); else return Query(L(u),l,mid) + Query(R(u),mid,r); } int main() { int n,Q,a,b,t; char cmd[2]; while(~scanf("%d%d",&n,&Q)) { for(int i=1;i<=n;i++) scanf("%d",&v[i]); Build(1,1,n+1); while(Q--) { scanf("%s%d%d",cmd,&a,&b); if(cmd[0] == 'Q') printf("%I64d\n",Query(1,a,b+1)); else { scanf("%d",&t); Updata(1,a,b+1,t); } } } return 0; }