http://codevs.cn/problem/1082/
"AC"
1#include <bits/stdc++.h>2 using namespacestd;3typedefLong Longll;4 Const intmaxn=2e5+2;5 intN;6 ll A[MAXN];7 ll C1[MAXN];8 ll C2[MAXN];9 intLowbit (intx)Ten { One returnx&-x; A } - voidAdd (ll *c,intk,ll val) - { the while(k<=N) { -c[k]+=Val; -k+=Lowbit (k); - } + } -ll query (ll *c,intk) + { All ans=0; at while(k) - { -ans+=C[k]; -k-=Lowbit (k); - } - returnans; in } -ll solve (intx) to { +ll ans=0; -ans+=x*query (c1,x); theans-=query (c2,x); * returnans; $ }Panax Notoginsengll solve (intXinty) - { the returnSolve (y)-solve (x1); + } A intMain () the { + while(~SCANF ("%d",&N)) - { $a[0]=0; $ for(intI=1; i<=n;i++) - { -scanf"%i64d",&a[i]); the //cout<<a[i]<<endl; -Add (c1,i,a[i]-a[i-1]);WuyiAdd (C2,i, (i-1) * (a[i]-a[i-1])); the } - intQ; Wuscanf"%d",&q); - intTP; About while(q--) $ { -scanf"%d",&tp); - if(tp==1) - { A intx,y;ll Val; +scanf"%d%d%i64d",&x,&y,&val); the Add (c1,x,val); -Add (c1,y+1,-val); $Add (c2,x,1ll* (X-1)*val); theAdd (c2,y+1, -1ll*y*val); the } the Else the { - intx, y; inscanf"%d%d",&x,&y); thell ans=solve (x, y); theprintf"%i64d\n", ans); About } the } the } the return 0; +}View Code
Principle
The principle is to use a poor fractional group, reproduced from http://www.cnblogs.com/boceng/p/7222751.html
The time complexity of the tree array is O (Mlogn), which is better than the segment tree and less written.
The Divine Ox is introduced in the differential fractional group, to maintain the differential array ks[i] = A[i]-a[i-1]; can easily get a[i] = Ks[1] + ks[2] + ... + ks[i]; That is, the first I item and, for convenience to remember as Sigma (KS, i), can already see the shadow of the tree array, so to find the interval and the resulting
A[1] + a[2] +.. + A[n] = Sigma (KS, 1) + Sigma (KS, 2) + ... + sigma (KS, N);
= N*ks[1] + (n-1) *ks[2] + ... + 2*ks[n-1] + 1*ks[n];
= N (ks[1] + ks[2] +...+ ks[n])-(0*ks[1] + 1*ks[2] + ... + (n-1) *ks[n]);
So you can get Sum[n] =n * Sigma (KS, N)-(0*ks[1] + 1*ks[2] + ... + (n-1) *ks[n]);
Make jk[i] = (i-1) * ks[i];
Then sum[n] = n * Sigma (KS, N)-Sigma (JK, N);
Then it constructs two tree-like arrays;
1 intLowbit (intk) {2 returnK &-K;3 }4 voidAddintNint*c,intKintva) {5 while(k <=N) {6C[k] + =va;7K + =Lowbit (k);8 }9 }Ten One //------------------------------------- A - for(i =1; I <= N; ++i) { -Add (n, C1, I, jk[i]-jk[i-1]); theAdd (n, c2, I, (i-1) * (jk[i]-jk[i-1])); -}View Code
Then make the query sum
1 intSigmaint*c,intk) {2 intsum =0;3 while(k) {4Sum + =C[k];5K-=Lowbit (k);6 }7 returnsum;8 }9 intGetsum (intSintt) {Ten return(T*sigma (c1, T)-sigma (C2, T))-((s1) *sigma (C1, S-1)-sigma (C2, S-1)); One}View Code
When you make a single point query, only two parameters are passed in to that point.
In the interval update, the god bull through two maintenance C1, two times C2 get, but I speculate a few cases, can not explain the reasons for doing so well,
1 void Update (intint int va) {2 Add (C1, S, VA); 3 Add (c1, t+1,-va); 4 Add (C2, S, va* (S-1)); 5 Add (c2, t+1,-va*t); 6 }
View Code
"Tree array interval revision interval sum" Codevs 1082 segment Tree Exercise 3