@@ -346,8 +346,11 @@ \subsubsection{区间加/区间求和}\label{ux533aux95f4ux52a0ux533aux95f4ux6c4
346346}
347347\end {minted }
348348
349+ \hypertarget {ux7ebfux6bb5ux6811ux6a21ux677f}{%
350+ \subsection {5.线段树模板 }\label {ux7ebfux6bb5ux6811ux6a21ux677f }}
351+
349352\hypertarget {ux6734ux7d20ux7ebfux6bb5ux6811}{%
350- \subsection { 4 .朴素线段树 }\label {ux6734ux7d20ux7ebfux6bb5ux6811 }}
353+ \subsubsection { (1) .朴素线段树 }\label {ux6734ux7d20ux7ebfux6bb5ux6811 }}
351354
352355区间和:区间修改/单点修改/单点查询/区间查询
353356
@@ -419,7 +422,7 @@ \subsection{4.朴素线段树}\label{ux6734ux7d20ux7ebfux6bb5ux6811}}
419422\end {minted }
420423
421424\hypertarget {ux52a8ux6001ux5f00ux70b9ux7ebfux6bb5ux6811}{%
422- \subsection { 5 .动态开点线段树 }\label {ux52a8ux6001ux5f00ux70b9ux7ebfux6bb5ux6811 }}
425+ \subsubsection { (2) .动态开点线段树 }\label {ux52a8ux6001ux5f00ux70b9ux7ebfux6bb5ux6811 }}
423426
424427\begin {minted }[fontsize=\footnotesize ,breaklines,linenos]{cpp}
425428namespace SegmentTree{
@@ -1942,8 +1945,8 @@ \subsection{13.CDQ 分治}\label{cdq-ux5206ux6cbb}}
19421945
19431946\end {minted }
19441947
1945- \hypertarget {ux73c2ux6735ux8389ux6811ux8001ux53f8ux673aux6811 }{%
1946- \subsection {14.珂朵莉树/老司机树 }\label {ux73c2ux6735ux8389ux6811ux8001ux53f8ux673aux6811 }}
1948+ \hypertarget {ux73c2ux6735ux8389ux6811ux8001ux53f8ux673aux6811ux533aux95f4ux63a8ux5e73 }{%
1949+ \subsection {14.珂朵莉树/老司机树(区间推平) }\label {ux73c2ux6735ux8389ux6811ux8001ux53f8ux673aux6811ux533aux95f4ux63a8ux5e73 }}
19471950
19481951\begin {minted }[fontsize=\footnotesize ,breaklines,linenos]{cpp}
19491952struct node{
@@ -2035,8 +2038,319 @@ \subsection{14.珂朵莉树/老司机树}\label{ux73c2ux6735ux8389ux6811ux8001ux
20352038}
20362039\end {minted }
20372040
2041+ \hypertarget {ux66ffux7f6aux7f8aux6811ux66b4ux529bux91cdux6784ux4e8cux53c9ux641cux7d22ux6811}{%
2042+ \subsection {15.替罪羊树(暴力重构二叉搜索树) }\label {ux66ffux7f6aux7f8aux6811ux66b4ux529bux91cdux6784ux4e8cux53c9ux641cux7d22ux6811 }}
2043+
2044+ 很暴力但是很牛逼的结构,平衡系数一般置为\( 0.75\) 即可。注意,二叉搜索树本质不变,所有二叉搜索树性质仍然适用。
2045+
2046+ 平衡系数越大插入速度就越快,而访问和删除速度就会降低。反之则插入变慢
2047+
2048+ \begin {minted }[fontsize=\footnotesize ,breaklines,linenos]{cpp}
2049+ const int N = 2e5 + 10;
2050+ double alpha = 0.75; //平衡系数
2051+
2052+ namespace SGT {
2053+ struct node {
2054+ int ls, rs;
2055+ int w, wn, s, sz, sd;
2056+ } tree[N];
2057+
2058+ int cnt, root;
2059+
2060+ //* recalculate the value of rt
2061+ void calc(int rt) {
2062+ tree[rt].s = tree[tree[rt].ls].s + tree[tree[rt].rs].s + 1;
2063+ tree[rt].sz = tree[tree[rt].ls].sz + tree[tree[rt].rs].sz + tree[rt].wn;
2064+ tree[rt].sd = tree[tree[rt].ls].sd + tree[tree[rt].rs].sd + (tree[rt].wn != 0);
2065+ }
2066+
2067+ //* determine if node k needs to be rebuild
2068+ bool can_rebuild(int rt) {
2069+ return tree[rt].wn && (alpha * tree[rt].s <= (double)max(tree[tree[rt].ls].s, tree[tree[rt].rs].s) || (double)tree[rt].sd <= alpha * tree[rt].s);
2070+ }
2071+
2072+ int ldr[N];
2073+
2074+ //* flatten the sub-tree of node rt in medium-order traversal
2075+ void rebuild_nf(int &ldc, int rt) {
2076+ if(!rt) return;
2077+ rebuild_nf(ldc, tree[rt].ls);
2078+ if(tree[rt].wn) ldr[ldc++] = rt;
2079+ rebuild_nf(ldc, tree[rt].rs); // if the current node has been deleted, then no retained it.
2080+ }
2081+
2082+ //* rebuild the part [l, r] to a binary search tree(in array ldr)
2083+ int rebuild_bd(int l, int r) {
2084+ if(l >= r) return 0;
2085+ int mid = l + r >> 1; // choose the mid value as the root to make it balanced
2086+ tree[ldr[mid]].ls = rebuild_bd(l, mid);
2087+ tree[ldr[mid]].rs = rebuild_bd(mid + 1, r);
2088+ calc(ldr[mid]);
2089+ return ldr[mid];
2090+ }
2091+
2092+ //* rebuild the sub-tree of node rt
2093+ void rebuild(int &rt) {
2094+ int ldc = 0;
2095+ rebuild_nf(ldc, rt);
2096+ rt = rebuild_bd(0, ldc);
2097+ }
2098+
2099+ //* insert a node ot the subtree of rt with value k
2100+ void insert(int &rt, int k) {
2101+ if(!rt) {
2102+ rt = ++cnt;
2103+ if(!root) root = 1;
2104+ tree[rt].w = k;
2105+ tree[rt].ls = tree[rt].rs = 0;
2106+ tree[rt].wn = tree[rt].s = tree[rt].sz = tree[rt].sd = 1;
2107+ } else {
2108+ if(tree[rt].w == k) tree[rt].wn++;
2109+ else if(tree[rt].w < k) insert(tree[rt].rs, k);
2110+ else insert(tree[rt].ls, k);
2111+ calc(rt);
2112+ if(can_rebuild(rt)) rebuild(rt);
2113+ }
2114+ }
2115+
2116+ //* delete the node with value k from the sub-tree of k
2117+ void del(int &rt, int k) {
2118+ if(!rt) return;
2119+ if(tree[rt].w == k) {
2120+ if(tree[rt].wn) tree[rt].wn--;
2121+ } else {
2122+ if(tree[rt].w < k) del(tree[rt].rs, k);
2123+ else del(tree[rt].ls, k);
2124+ }
2125+ calc(rt);
2126+ if(can_rebuild(rt)) rebuild(rt);
2127+ }
2128+
2129+ //* find the lowest ranking with a weight strictly greater than k
2130+ int upper_min(int rt, int k) {
2131+ if(!rt) return 1;
2132+ else if(tree[rt].w == k && tree[rt].wn)
2133+ return tree[tree[rt].ls].sz + tree[rt].wn + 1;
2134+ else if(tree[rt].w > k)
2135+ return upper_min(tree[rt].ls, k);
2136+ else
2137+ return tree[tree[rt].ls].sz + tree[rt].wn + upper_min(tree[rt].rs, k);
2138+ }
2139+
2140+ //* find the maximum ranking with a weight strictly less than k
2141+ int lower_max(int rt, int k) {
2142+ if(!rt) return 0;
2143+ else if(tree[rt].w == k && tree[rt].wn)
2144+ return tree[tree[rt].ls].sz;
2145+ else if(tree[rt].w < k)
2146+ return tree[tree[rt].ls].sz + tree[rt].wn + lower_max(tree[rt].rs, k);
2147+ else
2148+ return lower_max(tree[rt].ls, k);
2149+ }
2150+
2151+ //* find the exactly value of rank k
2152+ int getk(int rt, int k) {
2153+ if(!rt) return 0;
2154+ else if(tree[tree[rt].ls].sz < k && k <= tree[tree[rt].ls].sz + tree[rt].wn)
2155+ return tree[rt].w;
2156+ else if(tree[tree[rt].ls].sz + tree[rt].wn < k)
2157+ return getk(tree[rt].rs, k - tree[tree[rt].ls].sz - tree[rt].wn);
2158+ else
2159+ return getk(tree[rt].ls, k);
2160+ }
2161+
2162+ inline int find_pre(int rt, int k) {
2163+ return getk(rt, lower_max(rt, k));
2164+ }
2165+
2166+ inline int find_aft(int rt, int k) {
2167+ return getk(rt, upper_min(rt, k));
2168+ }
2169+ }
2170+
2171+ using SGT::root;
2172+
2173+ inline void solve() {
2174+ int n = 0; cin >> n;
2175+ for(int i = 1; i <= n; i++) {
2176+ int op, x; cin >> op >> x;
2177+ if(op == 1) SGT::insert(root, x);
2178+ else if(op == 2){
2179+ SGT::del(root, x);
2180+ }
2181+ else if(op == 3) {
2182+ int rnk = SGT::lower_max(root, x) + 1;
2183+ cout << rnk << endl;
2184+ } else if(op == 4) {
2185+ int k = SGT::getk(root, x);
2186+ cout << k << endl;
2187+ } else if(op == 5) {
2188+ int pre = SGT::find_pre(root, x);
2189+ cout << pre << endl;
2190+ } else if(op == 6) {
2191+ int aft = SGT::find_aft(root, x);
2192+ cout << aft << endl;
2193+ }
2194+ }
2195+ }
2196+ \end {minted }
2197+
2198+ \hypertarget {splay}{%
2199+ \subsection {16.Splay }\label {splay }}
2200+
2201+ \begin {minted }[fontsize=\footnotesize ,breaklines,linenos]{cpp}
2202+ #include <cstdio>
2203+ const int N = 100005;
2204+ int rt, tot, fa[N], ch[N][2], val[N], cnt[N], sz[N];
2205+
2206+ struct Splay{
2207+ void maintain(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x]; }
2208+
2209+ bool get(int x) { return x == ch[fa[x]][1]; }
2210+
2211+ void clear(int x) {
2212+ ch[x][0] = ch[x][1] = fa[x] = val[x] = sz[x] = cnt[x] = 0;
2213+ }
2214+
2215+ void rotate(int x){
2216+ int y = fa[x], z = fa[y], chk = get(x);
2217+ ch[y][chk] = ch[x][chk ^ 1];
2218+ if (ch[x][chk ^ 1]) fa[ch[x][chk ^ 1]] = y;
2219+ ch[x][chk ^ 1] = y;
2220+ fa[y] = x, fa[x] = z;
2221+ if (z) ch[z][y == ch[z][1]] = x;
2222+ maintain(x), maintain(y);
2223+ }
2224+
2225+ void splay(int x){
2226+ for (int f = fa[x]; f = fa[x], f; rotate(x))
2227+ if (fa[f]) rotate(get(x) == get(f) ? f : x);
2228+ rt = x;
2229+ }
2230+
2231+ void insert(int k){
2232+ if (!rt){
2233+ val[++tot] = k, cnt[tot]++;
2234+ rt = tot;
2235+ maintain(rt);
2236+ return;
2237+ }
2238+ int cur = rt, f = 0;
2239+ while (1){
2240+ if (val[cur] == k){
2241+ cnt[cur]++;
2242+ maintain(cur), maintain(f);
2243+ splay(cur);
2244+ break;
2245+ }
2246+ f = cur, cur = ch[cur][val[cur] < k];
2247+ if (!cur){
2248+ val[++tot] = k, cnt[tot]++, fa[tot] = f;
2249+ ch[f][val[f] < k] = tot;
2250+ maintain(tot), maintain(f);
2251+ splay(tot);
2252+ break;
2253+ }
2254+ }
2255+ }
2256+
2257+ int rk(int k){
2258+ int res = 0, cur = rt;
2259+ while (1){
2260+ if (k < val[cur]){
2261+ cur = ch[cur][0];
2262+ }
2263+ else{
2264+ res += sz[ch[cur][0]];
2265+ if (k == val[cur]){
2266+ splay(cur);
2267+ return res + 1;
2268+ }
2269+ res += cnt[cur], cur = ch[cur][1];
2270+ }
2271+ }
2272+ }
2273+
2274+ int kth(int k){
2275+ int cur = rt;
2276+ while (1){
2277+ if (ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
2278+ else{
2279+ k -= cnt[cur] + sz[ch[cur][0]];
2280+ if (k <= 0){
2281+ splay(cur);
2282+ return val[cur];
2283+ }
2284+ cur = ch[cur][1];
2285+ }
2286+ }
2287+ }
2288+
2289+ int pre(){
2290+ int cur = ch[rt][0];
2291+ if (!cur) return cur;
2292+ while (ch[cur][1]) cur = ch[cur][1];
2293+ splay(cur);
2294+ return cur;
2295+ }
2296+
2297+ int nxt(){
2298+ int cur = ch[rt][1];
2299+ if (!cur) return cur;
2300+ while (ch[cur][0]) cur = ch[cur][0];
2301+ splay(cur);
2302+ return cur;
2303+ }
2304+
2305+ void del(int k){
2306+ rk(k);
2307+ if (cnt[rt] > 1) {
2308+ cnt[rt]--;
2309+ maintain(rt);
2310+ return;
2311+ }
2312+ if (!ch[rt][0] && !ch[rt][1]){
2313+ clear(rt);
2314+ rt = 0;
2315+ return;
2316+ }
2317+ if (!ch[rt][0]) {
2318+ int cur = rt;
2319+ rt = ch[rt][1], fa[rt] = 0;
2320+ clear(cur);
2321+ return;
2322+ }
2323+ if (!ch[rt][1]) {
2324+ int cur = rt;
2325+ rt = ch[rt][0], fa[rt] = 0;
2326+ clear(cur);
2327+ return;
2328+ }
2329+ int cur = rt, x = pre();
2330+ fa[ch[cur][1]] = x;
2331+ ch[x][1] = ch[cur][1];
2332+ clear(cur);
2333+ maintain(rt);
2334+ }
2335+ } tree;
2336+
2337+ int main(){
2338+ int n, opt, x;
2339+ for (scanf("% d", &n); n; --n){
2340+ scanf("% d%d", &opt, &x);
2341+ if (opt == 1) tree.insert(x);
2342+ else if (opt == 2) tree.del(x);
2343+ else if (opt == 3) printf("% d\n", tree.rk(x));
2344+ else if (opt == 4) printf("% d\n", tree.kth(x));
2345+ else if (opt == 5) tree.insert(x), printf("% d\n", val[tree.pre()]), tree.del(x);
2346+ else tree.insert(x), printf("% d\n", val[tree.nxt()]), tree.del(x);
2347+ }
2348+ return 0;
2349+ }
2350+ \end {minted }
2351+
20382352\hypertarget {link-cut-tree}{%
2039- \subsection {15 .Link Cut Tree }\label {link-cut-tree }}
2353+ \subsection {17 .Link Cut Tree }\label {link-cut-tree }}
20402354
20412355\hypertarget {ux65e0ux6839ux6811ux7248ux672cmakeroot}{%
20422356\subsubsection {(1).无根树版本(MakeRoot) }\label {ux65e0ux6839ux6811ux7248ux672cmakeroot }}
@@ -2411,8 +2725,8 @@ \subsubsection{哈希表}\label{ux54c8ux5e0cux8868}}
24112725cc_hash_table<int, int> mp;
24122726\end {minted }
24132727
2414- \hypertarget {zkwux7ebfux6bb5ux6811ux4e0dux5e26ux4feermqonlog -log-no1}{%
2415- \subsection {\texorpdfstring {ZKW线段树+不带修RMQ(\( O(N\log \log N)+O(1)\) )}{ZKW线段树+不带修RMQ(O(N\textbackslash log \textbackslash log N)+O(1))} }\label {zkwux7ebfux6bb5ux6811ux4e0dux5e26ux4feermqonlog -log-no1 }}
2728+ \hypertarget {ux9644ux5f55zkwux7ebfux6bb5ux6811ux4e0dux5e26ux4feermqonlog -log-no1}{%
2729+ \subsection {\texorpdfstring {附录: ZKW线段树+不带修RMQ(\( O(N\log \log N)+O(1)\) )}{附录: ZKW线段树+不带修RMQ(O(N\textbackslash log \textbackslash log N)+O(1))} }\label {ux9644ux5f55zkwux7ebfux6bb5ux6811ux4e0dux5e26ux4feermqonlog -log-no1 }}
24162730
24172731普通的 zkw 线段树解法分为线性建树和单次 \( O(logn)\)
24182732的查询,显然查询是瓶颈。
0 commit comments