四道樹狀陣列模版題

2021-08-18 22:01:00 字數 1865 閱讀 4803

概念與實現就(lande)不寫了,反正一大堆

(嚴格來說其實不是模版題,但由於實際編碼接近模版題,當作模版題來說)

天文學家經常要檢查星星的地圖,每個星星用平面上的乙個點來表示,每個星星都有座標。我們定義乙個星星的「級別」為給定的星星中不高於它並且不在它右邊的星星的數目。天文學家想知道每個星星的「級別」。

5*4

*1 2 3

* * *

例如上圖,5號星的「級別」是3(1,2,4這三個星星),2號星和4號星的「級別」為1。

給你乙個地圖,你的任務是算出每個星星的「級別」。

(這圖要橫著看)

輸入的第一行是星星的數目n(1<=n<=60000),接下來的n行描述星星的座標(每一行是用乙個空格隔開的兩個整數x,y,0<=x,y<=32000)。

星星的位置互不相同。星星的描述按照y值遞增的順序列出,y值相同的星星按照x值遞增的順序列出。

由於說到(星星的描述按照y值遞增的順序列出,y值相同的星星按照x值遞增的順序列出。),就可以得出結論:每輸入一次x,輸出x位置的字首和,再將x加入樹狀陣列(這裡的先後順序可以保證不將自己算進答案中),可以得到答案:

以4為例,因為在之前字首和已經計算了比4的y值小的答案(y值遞增),又因為之前字首和已經計算了比4的x值小的答案(y值相同,x值遞增),所以正看時getsum(x)是4的左邊、正下方與左下方的所有星星個數。

所以實現的是乙個最基礎的樹狀陣列:

操作:1.單點修改

2.查詢字首和

int add(int x)

int getsum(int x)

操作:

1.單點修改

2.查詢區間和

這個沒什麼好說的,就是輸出稍作變動:

printf("%d\n",sum(y)-sum(x-1));
這個很好理解:

一數列a[1]-a[5]:1 2 8 6 30

字首和b[1]-b[5]:1 3 11 17 47

如果要查詢3-5的區間和:

a[3]+a[4]+a[5]=a[1]+a[2]+a[3]+a[4]+a[5]-a[1]-a[2]

=b[5]-b[2](這個總看得懂)

=b[5]-b[3-1]

所以……沒有所以了吧

操作:1.區間修改

2.單點查詢

區間修改要用到差分思想:

add(x,k);

add(y+1,-k);

如果x=2 y=5 k=3

在乙個長度為6數值為0的數列中:

修改後為0 3 0 0 -3

計算字首和:0 3 3 3 0

從x的位置開始計算+k,在遇到y+1時恢復(+k-k=0)

單點查詢也就是長度為1的區間查詢,不再贅述

操作:1.單點修改

2.查詢平面和

這波直接上**:

void add(int x,int y,int k)

return;

}//在二維平面內單點修改,相信還是看得懂的

int getsum(int x,int y)

return ans;

}//在二維平面內查詢二維字首和,相信也還是看得懂的

由於查詢的是二維字首和,還是要處理一下資料的:
printf("%d\n",getsum(x2,y2)+getsum(x1-1,y1-1)-getsum(x2,y1-1)-getsum(x1-1,y2));
字首和處理成平面和的方法與處理成區間和的方法大同小異,就不再說了

樹狀陣列模版

1.一維樹狀陣列 獲得2 k public static int lowbit int i 修改結點 public static void add int i,int value 求和 public static int getsum int i return sum 2.二維樹狀陣列 public...

樹狀陣列模版

單點更新,區間求和 include include using namespace std const intmaxn 1e6 1 inta maxn c maxn intmaxnum 1e6 intlowbit intx intsum intx return res void add intx,i...

樹狀陣列模版

原來聽到樹狀陣列這名字感覺很難,很高大上。學了一下發現不難。而且很好。普通的陣列修改某個值耗費為o 1 輸出和為o n 而樹狀陣列為o logn lowbit x 返回的是x二進位制最後一位1的位置 有公式 cn a n a k 1 an 其中 k 為 n 的二進位制表示中從右往左數的 0 的個數 ...