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...