樹狀數組應用

一維樹狀數組常用的3個函數

int lowbit(int x) //取x的最低位1,比如4,則返回4,如5,則返回1
{
	return x&(-x);
}

void update(int i, int val)  //將第i個元素增加val
{
	//i的祖先都要增加val
	while(i <= n)
	{
		sum[i] += val;
		i += lowbit(i);   //將i的二進制未位補爲得到其祖先
	}
}

int Sum(int i)   //求前i項的和
{
	int s = 0;
	//將前i項分段
	while(i > 0)
	{
		s += sum[i];
		i -= lowbit(i);  //去掉i的二進制最後一個
	}
	return s;
}


 

以下數組下標均默認從1開始

應用一

假如給你一個數組a[ ] = {2,5,3,4,1},b[i]b[i] 表示在a[1],a[2]...a[i-1](即位置i左邊)小於等於a[i]的數的個數。對此例b[] = {0,1,1,2,0}。 那麼該如何去求得b[i]呢?

解法:假如要得到b[4]的值,對於a[4] = 4. 我們 只要得到在a[1],a[2],a[3] 中出現小於等於4的個數,即1,2,3,4的個數,此例即爲2. a[1] = 2 < a[4], a[3] = 3 < a[4]. 所以b[4] = 2;其他的以此類推b[i]的值,需要得到在a[1],a[2]....a[i-1]中出現小於等於a[i]的個數,即1,2...a[i]的個數相當於求前a[i]項的和,可用到樹狀數組

具體操作

for(int i=1; i<=n; i++)

{

b[i] = getSum(a[i]); //求前a[i]項的和

update(a[i],1);      //a[i]個元素+1

}

應用二

假如給你一個數組a[ ] = {2,5,3,4,1},b[i]b[i] 表示在a[1],a[2]...a[i-1](即位置i左邊)大於等於a[i]的數的個數。對此例b[] = {0,0,1,1,4}。 那麼該如何去求得b[i]呢?

解法1只需要先將數組a倒過來編號,即將a轉換爲,a[] ={4,1,3,2,5}.此時具體的操作如應用一

解法2:改變更新路徑和求和路徑

void update(int x, int val)
{
	for(int i=x; i>0; i-=lowbit(i))
	{
		sum[i] += val;
	}
}

int getSum(int x)
{
	int s = 0;
	for(int i=x; i<MAXN; i+=lowbit(i))
	{
		s += sum[i];
	}
	return s;
}


 

應用三  逆序數

假如給你一個數組a[ ] = {2,5,3,4,1},b[i]b[i] 表示在a[i],a[i+1]...a[n](即位置i右邊)小於等於a[i]的數的個數。對此例b[] = {1,3,1,1,0}。 那麼該如何去求得b[i]呢?

操作:應用一位置i的左邊,應用三是位置i的右邊。 然後只需要在應用一的基礎上從後往前操作即可

for(int i=n; i>=1; i--)

{

b[i] = getSum(a[i]); //求前a[i]項的和

update(a[i],1);      //a[i]個元素+1

}

應用四

假如給你一個數組a[ ] = {2,5,3,4,1},b[i]b[i] 表示在a[i],a[i+1]...a[n](即位置i右邊)大於等於a[i]的數的個數。對此例b[] = {3,0,1,0,0}。 那麼該如何去求得b[i]呢?

操作:只需將數組a倒過來編號,即將a轉化爲 a[]={4,1,3,2,5} 然後利用應用三

 

二維樹狀數組

int lowbit(int x)
{
	return x&(-x);
}

void update(int x, int y, int val) //將 a[x][y] 的值增加val
{
	for(int i=x; i<N; i+=lowbit(i))
	{
		for(int j=y; j<N; j+=lowbit(j))
		{
			sum[i][j] += val;
		}
	}
}


int getSum(int x, int y) //求以1,1爲左上角端點,學校,x,y爲右下角端點的矩陣和.
{
	int s = 0;
	for(int i=x; i>0; i-=lowbit(i))
	{
		for(int j=y; j>0; j-=lowbit(j))
		{
			s += sum[i][j];
		}
	}
	return s;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章