数状数组求解:
下图是数状数组C和原数组a
数状形数组的规律:
•C1=a1
•C2=a1+a2
•C3=a3
•C4=a1+a2+a3+a4
•C5=a5
•……
•C8=a1+a2+a3+a4+a5+a6+a7+a8
•……
•C2n=a1+a2+….+a2^n
本质:对于序列a,数组C中的第x个元素为
C[x]
= a[x – 2k+
1] + … + a[x]
K为i的二进制表示中末尾0的个数
- 1) 与x对应的2k的计算
- int lowbit ( int x )
- {return x & (-x); }
-
- 2) a[k]增加d时,数组C中相应元素的修改
- //单点更新
- void change(int k,int d,int n)
- //n是数组的最大下标
- {while (k<=n)
- {c[k]=c[k]+d;
- k=k+lowbit(k);}
- }
//区间更新 多次单点更新
- 3)计算a[1]+a[2]+……+a[K]
- int getsum(int k)
- {int t=0;
- while (k>0)
- {t=t+c[k];
- k=k-lowbit(k);
- }
- return t;
- }
完整代码:
- #include <iostream>
- using namespace std;
- #define N 100
- int a[N],c[N];
- int lowbit(int x)
- {return x & (-x); }
- void change(int k,int d,int n)
- {while (k<=n)
- {c[k]=c[k]+d; k=k+lowbit(k); }
- }
- int getsum(int k)
- {int t=0;
- while (k>0)
- {t=t+c[k];k=k-lowbit(k);}
- return t;
- }
- int main( )
- { int i,n=8;
- memset(c,0,sizeof(c));
- for (i=1; i<=n; i++)
- { a[i]=i;change(i,i,n);}for (i=1; i<=n; i++)
- cout<<a[i]<<" "<<c[i]<<" "<<getsum(i)<<endl;
- a[3]=a[3]+50;
- change(3,50,8);
- for (i=1; i<=n; i++)
- cout<<a[i]<<" "<<c[i]<<" "<<getsum(i)<<endl;
- return 0;
- }