hdu 5975 樹狀陣列原理題

2021-07-24 17:07:15 字數 1237 閱讀 8501

lowbit[i]表示的其實就是i的二進位制表示中,不為0的最低位;

對於詢問1的區間[l,r],很好處理;

ans=cal(r)-cal(l-1);

cal(x)表示集合1到集合x,這x個集合一共加進去的數的個數;

加入集合k的數,根據題目給的公式可以推導出就是2^lowbit(k),即2的整數次冪;

所以直接列舉2的整數次冪即可在log(x)的時間複雜度裡快速得出cal(x)答案

1)當i為2的整數次冪,c[i]記錄的是a[1]到a[i]的前i項和

2)c[i]記錄的是a[i-lowbit(i)+1]到a[i]的lowbit(i)項和,第1個特點就是其中乙個特例

8前面的數1到7在進行,i+=lowbit(i)過程中都會到達8,這之後i+=lowbit(i) 相當於就不斷乘2;

[9,11]區間裡的數i+=lowbit(i)也會先到達12,再16,之後i+=lowbit(i) 也是相當於不斷乘2;

這樣c[i]有另一種理解方式,記錄的是a[k+1]到a[i]的和,其中k表示i之前lowbit(k)大於lowbit(i)的最大值;

對於c[12]來說k就是8; 對於c[14]來說k就是12

3)有了第2點作為基礎,要記錄a陣列的前i項和只需要

int answer=0;

while(i>0)

return answer;

4)對於i和i+lowbit(i)之間的數(不包括這兩個本身)m,lowbit(m)必定小於lowbit(i)

並且,假設c[m]記錄的是區間[l,r]的所有a[ ]值和,那麼必有i

i+lowbit

5)有了第4點的基礎

對於a[k],它的值被哪些c[i]加進去了

可以這麼寫

int i=k;

while(i

<=n)

//**如下

ll cal(ll x)

int main()

else

}printf("%lld\n",ans);}}

//fre2();

return

0;}

hdu 2838 樹狀陣列水題

提議是給你乙個序列 讓你調整把它變成 從小到大排列的有序序列 沒調動兩個為兩權值之和 問最小的權值和是多少 給個數列 1 4 2 3 5 對每乙個位置數 需要交換的比為前面比它大的數 或後面比它小的數 包含了最小值在裡面了 比如pi前面有5個數比它大 則就需要把這5個數和pi交換 交換的權值就是這5...

hdu 1594 樹狀陣列 水題

思路 乙個座標的level和它的y座標是無關的,因為x和y都是公升序leve給出的,乙個座標的level只和前面所有的x有關,那麼可以抽象這麼乙個a陣列 實際上是不存在的,只是抽象出來 每輸入乙個x,就對a x 1 因為有0 當前a 1 a x 1 的和就是該座標的level,那麼這個a陣列就可以用...

HDU 4417 水題 樹狀陣列

題目大意 給n個數字,m個詢問 每次詢問 l,r 區間的數字,比k小的數字有多少個。下標從0 n 1 直接離線後樹狀陣列,聽說劃分樹也能過 略微更新的我的破爛離散化小板子 include using namespace std define pr x cout x vectormp maxn voi...