動態開點建樹即可。
void build(int &o,int l,int r)
build(ls[o],l,mid);
build(rs[o],mid+1,r);
return;
}
左右子節點繼承上一版本即可,注意$sum$應當較上一版本$+1$。
void update(int &o,int l,int r,int pre,int x)
if(x<=mid)
else
}
注意是用右邊界的左子節點減去左邊界的左子節點。
int kth(int l,int r,int x,int y,int k)
int tmp=sum[ls[y]]-sum[ls[x]];
if(k<=tmp)
else
}
板子我是用$namespace$寫的,放在這方便以後用。
注意線段樹的陣列開40倍。
#define n 200010
#define mid ((l+r)>>1)
int n,m,siz,ind;
int rt[(n<<5)+(n<<3)],ls[(n<<5)+(n<<3)],rs[(n<<5)+(n<<3)],sum[(n<<5)+(n<<3)],a[n],b[n];
namespace persistence_segment_tree
return; }
void build(int &o,int l,int r)
build(ls[o],l,mid);
build(rs[o],mid+1,r);
return; }
void update(int &o,int l,int r,int pre,int x)
if(x<=mid)
else }
void init() }
int kth(int l,int r,int x,int y,int k)
int tmp=sum[ls[y]]-sum[ls[x]];
if(k<=tmp)
else }
void solve()
return;
}}
主席樹(可持久化線段樹)
我真弱。連主席樹都不會。主席樹相當於多個線段樹,由於相鄰兩棵線段樹的節點的值只有少許不同,因此可以對於和前一棵樹一樣的子樹乙個指標指過去,無需操作,這樣每棵樹o logn 總複雜度o nlogn 以下是區間k大 include include include define n 100005 defi...
主席樹 可持久化線段樹
首先要學會普通的線段樹,然後理解權值線段樹,而主席樹就是多個權值線段樹 我自己的理解 但是這多個權值線段樹之間有公共部分,節約了空間。它一開始是乙個空樹,後來逐個添數,記錄新增的這個數在那個範圍內,並 1,顯然它每次只更新了一條鏈,其他不需要變,這樣就有了多個版本的線段樹。如果求 l,r 範圍內第k...
可持久化線段樹(主席樹)
qwq我大概又是機房最後乙個學主席樹的了吧 其實之前一直都在講 只是沒做題 做了幾道以後發現都是乙個套路qwq關鍵就是能不能看出來要用主席樹 主要可以解決 靜態 動態區間第k大 樹上也可以 一些有關區間的帶某些限制的詢問 如出現次數等 先把模板粘上來 include include include ...