由於ut並不會可持久化平衡樹,因此他決定用一種奇怪的方法ac此題。
空間:線性。
缺點:離線。
首先,每個更新/查詢都是基於乙個歷史版本的。
查詢先不管,就看更新,相當於每個點有乙個「父親」,總的形成乙個樹結構(!
每個更新,相當於樹上的一條邊。
然後轉回來處理查詢,可以認為是在每個節點後面拖了一串詢問。
那接著怎麼做相信應該不難想到了吧?維護一棵平衡樹然後dfs此更新樹~
向下的時候,相當於直接操作。
回溯的時候,相當於是撤銷了一條邊上的操作。
看看操作,一加一刪,正好支援撤銷~
加變刪,刪變加(臨時存一下被刪掉的數)就好了。
然後,每進入到乙個節點的時候,就把拖著的一串詢問回答掉。
over~
細節基本沒有。
方便起見,使用了fhq-treap。
然後就是挫**了(
#include #pragma gcc optimize("ofast", 3, "inline")
#pragma comment(linker, "/stack:102400000,102400000")
using namespace std;
const int n = 1e6 + 9;
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
struct node tree[n];
int tot, root;
int newnode(int x) ;
return tot;
}void pushup(int x)
void split(int now, int k, int& l, int& r)
if (tree[tree[now].l].sz < k) else
pushup(now);
}int merge(int x, int y) else
}int kth(int k)
}void insert_t_as_kth(int t, int k)
void delete_kth(int k)
void print(int now)
void print()
const int __n__ = 3e5 + 9;
int fa[__n__], op[__n__], k[__n__], t[__n__];
int id[__n__];
vectorout[__n__];
vectorquery[__n__];
int ans[n];
int cnt;
void dfs(int now)
for (int to : out[now]) else
}}int read()
int main()
dfs(0);
for (int i = 1; i <= m; ++i)
if (~ans[i]) printf("%d\n", ans[i]);
return 0;
}
LOJ120 持久化序列 rope
使用rope,需要引入標頭檔案ext rope,並且使用命名空間 gnu cxx 定義roperp 簡單用例 rope rp maxn his 0 new rope his i new rope his i 1 常見操作 功能 push back x 在末尾追加元素x insert pos,x 插入...
LOJ 持久化序列 可持久化treap
一道模板題 在寫完這道題以後就去找其他帶翻轉的可持久化treap題去寫了 發現自己根本不會可持久化treap 什麼標記翻轉可持久化 自閉了一整天 網上也沒有找到很好的模板 於是選擇擱置一段時間 等以後時間充裕了再來磕 includeusing namespace std const int maxn...
loj6088 可持久化最長不降子串行
考慮二分求lis的過程,就是維護乙個序列,其中第i個數表示長度為i的最小結尾,而插入操作就是查詢第乙個大於x的位置並替換掉 用線段樹維護,二分的過程也可以用線段樹來完成,對線段樹可持久化即可 1 include2 using namespace std 3 define n 500005 4 def...