序列操作IV 樹狀陣列套線段樹 樹套樹

2022-06-01 08:15:07 字數 1599 閱讀 3955

給出序列 a1,a2,…,an(0≤ai≤109),有關序列的兩種操作。

1. ai(1≤i≤n)變成 x(0≤x≤109)。

2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1≤k≤r-l+1)小。

第一行包含兩個數 n(1≤n≤2×104)和 m(1≤m≤2×104),表示序列長度和操作次數。

接下來一行 n 個數,以空格隔開,表示 a1,a2,…,an 。

接下來m行,每行為以下兩種格式之一:

對於每次詢問,輸出單獨的一行表示答案。

5 3 

1 2 3 4 5 

1 1 5 3 

0 3 5 

1 1 5 3

4

本題有多種解法。這裡先講一下較為簡單的樹狀陣列套線段樹。

外層樹狀陣列n個節點分別對應下標,每個節點其實是乙個權值為下標的線段樹的根節點(一共有n顆),那麼樹狀陣列中的i號點表示的就是區間為1~i的元素,而其下的權值線段樹則記錄在該區間的權值出現次數。

由於樹狀陣列有字首和的性質,插入時會更新它及其以後的所有樹,詢問時也能訪問它及其以前的所有樹,所以要查詢l~r的k小,就只需要將有關區間的點放入乙個陣列,然後分別進入左子樹、右子樹查詢即可。

看看**很好理解。

#include#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int n = 2e4 + 5, m = 2e6 + 5

;int len, a[n], b[n * 2

], root[n], tot;

intcur[n], n, m;

struct

nodetr[m];

struct

qryq[n];

inline

intread()

inline

void wr(int

x)inline

void

disc_init()

inline

void insert(int &k, int l, int r, int p, int

v)inline

void update(int k, int p, int

v)inline

void gotopos(int lx, int

rx)inline

int cntlc(int lx, int

rx)inline

int query(int nl, int nr, int l, int r, int

k)

else

}inline

void

tree_init()

intmain()

disc_init();

tree_init();

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

else

}}

權值線段樹套序列線段樹

p3380 模板 二逼平衡樹 樹套樹 主要思路如下 外層為權值線段樹,內層為動態開點線段樹,也就是每個權值線段樹上的節點開乙個動態開點線段樹。外層的權值線段樹支援查詢排名,內層的線段樹限制了區間。實際上就是在普通權值線段樹上查詢的價值變成了在其線段樹上區間查詢返回的值。對於這道模板題,我們先寫幾個函...

區間操作 樹狀陣列 線段樹

涉及區間操作的一些套路必須要會呀 區間加減為了偷懶能不寫線段樹so我選擇樹狀陣列!但是區間乘除,最大值我想了想還是用線段樹分塊吧。這裡用網上的一張圖 這裡灰色陣列是原本的陣列 a i 紅色陣列則是樹狀陣列 c i 這裡直接給出結論 c i a i 2 k range 1,2 k k是i的二進位制位從...

區間操作 樹狀陣列 線段樹

涉及區間操作的一些套路必須要會呀 區間加減為了偷懶能不寫線段樹so我選擇樹狀陣列!但是區間乘除,最大值我想了想還是用線段樹分塊吧。這裡用網上的一張圖 這裡灰色陣列是原本的陣列 a i 紅色陣列則是樹狀陣列 c i 這裡直接給出結論 c i a i 2 k range 1,2 k k是i的二進位制位從...