数状数组
数状数组求解:
下图是数状数组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;
}