權值線段樹的模板

2021-10-05 17:11:49 字數 1765 閱讀 2676

#

include

#include

#include

#include

#include

#include

#include

using

namespace std;

const

int maxn=

1e5+10;

int num[maxn*5]

;//權值線段樹:

//區間的值是這段值域裡的個數的線段樹

//葉子結點的值 是這個數在序列裡出現的次數

//可以當平衡樹用 比平衡樹**好寫

/* 沒有必要build

多組樣例的時候

memset就搞定了

void build(int p,int l,int r)

int mid=(l+r)>>1;

build(p<<1,l,mid);

build(p<<1|1,mid+1,r);

} */

void

update

(int p,

int l,

int r,

int v,

int op)

//op==1或-1,插入或刪除

intkth

(int p,

int l,

int r,

int rank)

//k小值

//求乙個數的最小排名,排名從0起

intrank

(int p,

int l,

int r,

int v)

//[1,v-1]的出現個數 即v-1>mid 即前面3個數v就rank3

intfindpre

(int p,

int l,

int r)

//找前驅 盡可能在小於v的右子樹找

intpre

(int p,

int l,

int r,

int v)

int mid=

(l+r)

>>

1,re;

//如果v在右子樹可能有前驅(至少mid+1比v小)就先查右子樹,l=mid+1

if(mid+

11]&&(re=

pre(p<<1|

1,mid+

1,r,v)))

return re;

//否則查左子樹,r=mid,使r不斷變小直至滿足題意小於v

return

pre(p<<

1,l,mid,v);}

intfindnext

(int p,

int l,

int r)

//找後繼 盡可能在大於v的左子樹找

intnext

(int p,

int l,

int r,

int v)

int mid=

(l+r)

>>

1,re;

//如果左子樹里有比v大的(至少mid比v大)就查左子樹 否則查右子樹

if(v&&(re=

next

(p<<

1,l,mid,v)))

return re;

return

next

(p<<1|

1,mid+

1,r,v);}

intmain()

權值線段樹 模板

ps 維護區間和,時間複雜度 o n logn o nlogn o nlog n include using namespace std typedef long long ll define lson l,m,rt 1 define rson m 1,r,rt 1 1 define pushup ...

權值線段樹

維護全域性的值域資訊,每個節點記錄的是該值域的值出現的總次數。使用二分的思想 離散化的時候,需要用到 支援查詢全域性k小值,全域性rank,前驅,後繼等。單詞操作時間複雜度為o logn 空間複雜度為o n 相對於平衡樹的優勢 簡單,速度快 劣勢 值域較大時,我們需要離散化,變成離線資料結構 我認為...

權值線段樹

include using namespace std int n,m,tre 10003 4 laz 10003 4 void pushdown int num void update int num,int le,int ri,int x,int y,int z pushdown num int...