模板汇总——treap
1. 旋转treap。
思想:一颗权值BST + 一颗 随机数 最小堆。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; #define inf 300000030 const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; struct Treap{ int L[N], R[N], sz[N], v[N], rnd[N], ct[N], tot, root; void init(){ tot = root = 0; } inline int rand(){ static int seed = 12345; return seed = (int)seed * 482711LL % 2147483647; } void Updata(int p){ sz[p] = ct[p] + sz[L[p]] + sz[R[p]]; } void turnL(int &k){ int t = R[k]; R[k] = L[t]; L[t] = k; sz[t] = sz[k]; Updata(k); k = t; } void turnR(int &k){ int t = L[k]; L[k] = R[t]; R[t] = k; sz[t] = sz[k]; Updata(k); k = t; } void Insert(int &p, int x){ if(!p){ p = ++tot; sz[p] = ct[p] = 1; v[p] = x; rnd[p] = rand(); return ; } sz[p]++; if(v[p] == x) ct[p]++; else if(x > v[p]){ Insert(R[p], x); if(rnd[R[p]] < rnd[p]) turnL(p); } else { Insert(L[p], x); if(rnd[L[p]] < rnd[p]) turnR(p); } } void Delete(int &p, int x){ if(!p) return ; if(v[p] == x){ if(ct[p] > 1) ct[p]--, sz[p]--; else { if(L[p] == 0 || R[p] == 0) p = L[p] + R[p]; else if(rnd[L[p]] < rnd[R[p]]) turnR(p), Delete(p, x); else turnL(p), Delete(p, x); } } else if(x > v[p]) sz[p]--, Delete(R[p], x); else sz[p]--, Delete(L[p], x); } int Query_Rank_of_x(int p, int x){ if(!p) return 0; if(v[p] == x) return sz[L[p]]+1; if(v[p] > x) return Query_Rank_of_x(L[p], x); return ct[p] + sz[L[p]] + Query_Rank_of_x(R[p], x); } int Query_kth(int p, int k){ if(!p) return -1; if(sz[L[p]] >= k) return Query_kth(L[p], k); k -= sz[L[p]]; if(k <= ct[p]) return v[p]; k -= ct[p]; return Query_kth(R[p], k); } int FindFront(int p, int x){ if(!p) return -inf; if(v[p] < x) return max(v[p], FindFront(R[p], x)); return FindFront(L[p], x); } int FindNext(int p, int x){ if(!p) return inf; if(v[p] <= x) return FindNext(R[p], x); return min(v[p], FindNext(L[p], x)); } }treap; int main(){ int T; int op, x; scanf("%d", &T); treap.init(); while(T--){ scanf("%d%d", &op, &x); if(op == 1) treap.Insert(treap.root, x); else if(op == 2) treap.Delete(treap.root, x); else if(op == 3) printf("%d\n", treap.Query_Rank_of_x(treap.root, x)); else if(op == 4) printf("%d\n", treap.Query_kth(treap.root, x)); else if(op == 5) printf("%d\n", treap.FindFront(treap.root, x)); else if(op == 6) printf("%d\n", treap.FindNext(treap.root, x)); } return 0; }
2.无旋 + 可持久化Treap
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 3e6; const int M = 2e5 + 100; int a[M], top; int n, m; struct Treap{ int L[N], R[N], sz[N], v[N], tot, root, prt; LL sum[N]; inline void init(){ prt = root = tot = 0; } inline void PushUp(int x){ sz[x] = 1 + sz[L[x]] + sz[R[x]]; sum[x] = v[x] + sum[L[x]] + sum[R[x]]; } inline int NowNode(int val){ ++tot; L[tot] = R[tot] = 0; sz[tot] = 1; v[tot] = sum[tot] = val; return tot; } inline int CopyNode(int pre){ ++tot; L[tot] = L[pre]; R[tot] = R[pre]; sz[tot] = sz[pre]; v[tot] = v[pre]; sum[tot] = sum[pre]; return tot; } pll Split(int x, int k){ if(!x) return pll(0, 0); pll y; x = CopyNode(x); if(sz[L[x]] >= k){ y = Split(L[x], k); L[x] = y.se; PushUp(x); y.se = x; } else { y = Split(R[x], k-sz[L[x]]-1); R[x] = y.fi; PushUp(x); y.fi = x; } return y; } int Merge(int x, int y){ if(!x || !y) return x | y; if(rand() % (sz[x] + sz[y]) <= sz[x]){ x = CopyNode(x); R[x] = Merge(R[x], y); PushUp(x); return x; } else { y = CopyNode(y); L[y] = Merge(x, L[y]); PushUp(y); return y; } } LL Query_kth_sum(int x, int k){ if(!x || !k) return 0; if(sz[L[x]] >= k) return Query_kth_sum(L[x], k); return Query_kth_sum(R[x], k-sz[L[x]]-1) + sum[L[x]] + v[x]; } LL Querysum(int l, int r){ return Query_kth_sum(root, r) - Query_kth_sum(root, l-1); } void Updata1(int l, int r, int k){ /// ... l-k ... l .... r .... n pll p1 = Split(root, r); pll p2 = Split(p1.fi, l-1); pll p3 = Split(p2.fi, l-k-1); int zzz = p3.se; while(sz[zzz] < r - l + 1) zzz = Merge(zzz, zzz); pll p4 = Split(zzz, r-l+1); root = Merge(p2.fi, p4.fi); root = Merge(root, p1.se); } void Updata2(int l, int r){ pll p1 = Split(prt, r); p1 = Split(p1.fi, l-1); pll p2 = Split(root, r); pll p3 = Split(p2.fi, l-1); root = Merge(p3.fi, p1.se); root = Merge(root, p2.se); } void Build(int & x, int l, int r){ if(l > r) {x = 0; return;} int m = l+r >> 1; x = NowNode(a[m]); Build(L[x], l, m-1); Build(R[x], m+1, r); PushUp(x); } void dfs(int x){ if(!x) return ; dfs(L[x]); a[++top] = v[x]; dfs(R[x]); } void ReBuild(){ tot = sz[prt]; top = 0; dfs(root); Build(root, 1, n); } }treap; int main(){ treap.init(); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); treap.Build(treap.root, 1, n); treap.prt = treap.root; int MaxP = 2e6 + 5e5; int op, l, r, k; for(int i = 1; i <= m; ++i){ scanf("%d", &op); if(op == 1) { scanf("%d%d", &l, &r); printf("%lld\n", treap.Querysum(l, r)); } else if(op == 2){ scanf("%d%d%d", &l, &r, &k); treap.Updata1(l, r, k); } else { scanf("%d%d", &l, &r); treap.Updata2(l, r); } if(treap.tot > MaxP){ treap.ReBuild(); } } return 0; }
3.普通treap
19牛客多校4F
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 1e5 + 100; int n, m; struct Treap{ int L[N], R[N], sz[N], v[N], tot, root, prt, key[N]; int Max[N]; inline void init(){ root = tot = 0; } inline void PushUp(int x){ sz[x] = 1 + sz[L[x]] + sz[R[x]]; Max[x] = max({v[x], Max[L[x]], Max[R[x]]}); } void Split(int x, int k, int &l, int &r){ if(!x) {l = r = 0; return ;} if(sz[L[x]] >= k){ r = x; Split(L[x], k, l, L[x]); } else { l = x; Split(R[x], k-sz[L[x]]-1, R[x], r); } if(l) PushUp(l); if(r) PushUp(r); } int Merge(int x, int y){ if(!x || !y) return x | y; if(key[x] > key[y]){ R[x] = Merge(R[x], y); PushUp(x); return x; } else { L[y] = Merge(x, L[y]); PushUp(y); return y; } } inline void NowNode(int val){ ++tot; L[tot] = R[tot] = 0; sz[tot] = 1; v[tot] = Max[tot] = val; key[tot] = rand(); root = Merge(root, tot); } int Query_kth(int x, int k){ if(sz[L[x]] >= k) return Query_kth(L[x], k); else k -= sz[L[x]]; if(k == 1) return v[x]; k -= 1; return Query_kth(R[x], k); } int get_lens(int x, int val){ if(!x) return 0; if(Max[L[x]] > val) return get_lens(L[x], val); if(v[x] > val) return sz[L[x]]; return sz[L[x]] + 1 + get_lens(R[x], val); } void solve(){ int l, m, r; scanf("%d%d%d", &l, &m, &r); int t1, t2, t3; Split(root, r, t1, t2); root = t1; Split(root, m, t1, t3); root = 0; while(t1 && t3){ int A = Query_kth(t1, 1), B = Query_kth(t3, 1); if(A > B) { swap(A, B); swap(t1, t3); } int len = get_lens(t1, B), tmp; Split(t1, len, tmp, t1); root = Merge(root, tmp); } if(t1) root = Merge(root, t1); if(t3) root = Merge(root, t3); root = Merge(root, t2); } }treap; int main(){ treap.init(); srand(time(0)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i){ int v; scanf("%d", &v); treap.NowNode(v); } int op; for(int i = 1; i <= m; ++i){ scanf("%d", &op); if(op == 1) treap.solve(); else { scanf("%d", &op); printf("%d\n", treap.Query_kth(treap.root, op)); } } return 0; }