關於樹狀陣列的一些討論

2021-08-09 15:38:50 字數 2197 閱讀 6411

樹狀陣列用於在log(n)的時間複雜度修改與詢問字首

相比線段樹更好寫 常數更小 不過侷限性很大 不能用於維護最大最小值之類的情況

最常用的應用(我用過的)大概有:

單點修改區間查詢

區間修改單點查詢

區間修改區間查詢

離散化權值求逆序對

以上內容**洛谷金秋講義

上面已經把樹狀陣列定義以及修改查詢方法講的很細緻了

值得特別提出來的是lowbit的證明部分:

設a』為a的二進位制反碼,i的二進位制表示成xx1yy,其中yy為全0序列,xx可以忽略(因為對lowbit沒有貢獻最後都會歸零) 那麼-i = x』x』0 y』y』+1(計算機中負數的儲存方式 反碼+1) 由於yy是全0 序列 那麼反碼y』y』就是全1序列 再加上1 那就又變成了全0序列 首位進1 那麼-i=x』x』1yy 所以呢 i&-i=xx1yy&x』x』1yy=1yy 即2^k的值(k是i二進位制末尾0的個數)

接下來是基本**:

int lowbit(int x)

void add(ll c,int x,int k)

}ll query(ll c,int x)

return ans;

}

有了上面的**就可以:

單點修改區間查詢:

反正能夠log(n)修改,

log(n)查詢字首和,

減一減就是了

關於逆序對:

離散化之後倒序加入每次統計字首和(後邊比當前小的數的個數)

區間修改單點查詢:

這個需要用樹狀陣列維護乙個記錄每個點修改情況的差分陣列delta,在修改區間(l,r)的時候只需要修改r+1 和 l

查詢x時輸出a[x]+sum[x]就可以

區間修改區間查詢:

這個比較麻煩了

需要推一推式子

上面區間修改時利用了差分陣列delta

即 a』[ x ] = a[ x ]+delta[ 1 ]+delta[ 2 ] … + delta[ x ]

區間查詢時用到了字首和陣列

那麼我們可不可以綜合起來用來實現區間修改區間查詢呢

當然了!

來看下面

a』[ x ] = a[ x ]+delta[ 1 ]+delta[ 2 ] … + delta[ x ]

a』[ x-1 ] = a[ x-1 ]+delta[ 1 ]+ … + delta[ x-1 ]

······

a』[ 1 ] = a[ 1 ]+delta[ 1 ]

==>sum』[ x ] = sum [ x ] + x*delta[ 1 ] +(x-1) * delta[ 2 ]+..+1 * delta[ x ]

觀察右邊delta類似乙個倒三角

大概是 。。這樣

這樣不好弄啊

那我們把他補一下 像這樣

那麼我們發現

只需要維護乙個delta[ ]的字首和 乙個delta[x] * x 的字首和就可以求出後邊一部分式子了

即 紅色部分 = delta[ ]字首和(x+1) (矩形)- delta[x] x 字首和(藍色部分)

於是每次查詢(l , r)就變成了

ans=( sum[r]+ deltasum[ r ] * (r+1) - deltaxsum[ r ])-( sum[ l-1 ] +deltasum[ l-1 ]* l -deltaxsum[ l-1 ] )

the end

關於Session的一些討論

眾所周知,session是jsp的九大內建物件之一,也是伺服器二次識別客戶端的橋梁,它的生命週期非常長,一般都是存在於乙個會話 同一瀏覽器 之中,與 天地同壽 伺服器 有如下例子 1 在不關閉瀏覽器的情況下,建立乙個session,你始終可以訪問到這個session。2 在不關閉瀏覽器的情況下,建立...

關於樹狀陣列一些有意思的東西

嘛 最近剛剛學會樹狀陣列,寫個blog記錄一下心得。樹狀陣列呢,核心是乙個叫lowbit的東西,lowbit x x x x的最後一位1的大小。一 乙個經典問題 乙個初始值為0的k位計數器,要求支援n次 1操作。時間複雜度?經典解法 法i 考慮第i位的改變次數,可得o k 1 i 0n 2i o i...

一些簡單的樹狀陣列題

大意 給定一列數 a i 求滿足下列條件的數對 x,y 的數量 1 xn 與 a i n 是等價的,所以直接將大於n的 a i 賦為 n 可以避免離散化 include include include include include include include include using nam...