樹狀陣列的一系列操作

2022-03-14 09:22:46 字數 2090 閱讀 8954

1、樹狀陣列求逆序對

#include

#include

#include

using

namespace

std;

const

int maxn=100010;

int n,a[maxn],b[maxn],c[maxn],s[maxn];

int lowbit(int x)

void add(int x)

int getsum(int x)

int main()

int ans=0;

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

cout

0;}

2、樹狀陣列區間修改

這裡由於涉及到區間修改,所以我們要引入差分的思想。

差分陣列c:我們設sigma(c,i)表示c陣列的前i項和,呼叫一次的複雜度是log2(i)

設原陣列是a[n],差分陣列c[n],c[i]=a[i]-a[i-1],那麼明顯地a[i]=sigma(c,i),如果想要修改a[i]到a[j],只需令c[i]+=v,c[j+1]-=v

明白了上面的原理以後,就可以直接看**了

/*區間修改+單點查詢*/

#include

#include

using

namespace

std;

const

int maxn=500010;

int n,m,a[maxn],c[maxn];

int lowbit(int x)

void add(int x,int y)

int getsum(int x)

int main()

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

else

}return

0;}

/*單點修改+區間查詢*/

#include

#include

using

namespace

std;

const

int maxn=500010;

int n,m,c[maxn];

int lowbit(int x)

void add(int x,int y)

int getsum(int x)

int main()

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

else

}return

0;}

注意:

樹狀陣列c始終是字首和陣列,即:getsum(i)始終得到的是點i的字首和。

區間修改是將樹狀陣列變成了差分陣列,所以getsum(i)得到的是差分字首和,由上面的推導,i的差分字首和,就是點i的值,所以getsum(i)是單點查詢,即:getsum(i)==a[i]

單點修改不需要差分,所以樹狀陣列維護的就是x的字首和,即getsum(x)==a[1]+a[2]+……+a[x],此時getsum()函式變成了區間查詢函式

舉個例子:x~y的區間和==getsum(y)-getsum(x-1)

拓展:

(兩個差分陣列還原了字首和陣列orz~~)

#include

#include

using

namespace

std;

const

int maxn=200010;

int n,m,s[maxn],t[maxn],r[maxn];

int lowbit(int x)

void add1(int x,int y)

void add2(int x,int y)

int find1(int x)

int find2(int x)

int getsum(int x)

int main()

scanf("%d",&m);

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

else

}return

0;}

關於mysql 一系列操作

這是在linux 的mysql的資料庫操作,備份資料庫 mysqldump u root p cxn usr local backupcxn.sql 引數說明 cxn 代表著我要備份的資料庫名稱,usr local backupcxn.sql代表著備份到usr local下,輩分的名稱叫做backu...

模擬動態陣列及其一系列操作

線性表是一種資料結構。在邏輯上,具有除了第乙個結點,其他結點有唯一前驅,除了最後乙個結點,其他結點有唯一後驅的特點。順序表和鏈式表是線性表的兩種實現方式,它們只在儲存方式上有區別,在邏輯上是一致的。區別在於順序表示使用連續的一段空間來儲存,我們常用的陣列就是線性表的一種順序表示。陣列是靜態分配記憶體...

SQL JOIN的一系列操作 嘎 嘎 嘎

誰訂購了產品,並且他們訂購了什麼產品?除了我們在上面的例子中使用的 inner join 內連線 我們還可以使用其他幾種連線。下面列出了您可以使用的 join 型別,以及它們之間的差異。right join 關鍵字會右表 table name2 那裡返回所有的行,即使在左表 table name1 ...