維護長度 n ≤ 50000 有序序列,支援 m ≤ 50000 次操作:
[l,r] 中 k 的排名[l,r] 中排名第 k 的值pos → k[l,r] 中 k 的前驅(<k 最大值)[l,r] 中 k 的後繼(>k 最小值)O(log n) 插入、刪除、查排名、查前驅後繼。O(log n) 個 Treap。O(log n) 個線段樹節點,合併結果。val, pri, cnt, size, ch[2]。pushup 維護 size。rotate 維護堆序性。rank(x) 回傳 <x 的個數。rank(mid) 判斷。<x / 最小 >x,線段樹合併取 max/min。O(n log² n)(每值插入 log n 層,每層 Treap 插入 log n)。O(log² n)。≈ n log n,n=5e4 時 ~1e6 節點,~100MB 以內。struct TreapNode {
int val, pri, cnt, sz, ch[2];
} t[MAXN * 20];
int tot = 0;
void pushup(int u) { t[u].sz = t[t[u].ch[0]].sz + t[t[u].ch[1]].sz + t[u].cnt; }
void rotate(int &u, int d) { /* d=0 右旋, d=1 左旋 */ }
void insert(int &u, int x) { /* 標準 Treap 插入 */ }
void erase(int &u, int x) { /* 標準 Treap 刪除 */ }
int rank(int u, int x) { /* 返回 > 1;
build(u<<1, l, mid); build(u<<1|1, mid+1, r);
}
void modify(int u, int pos, int oldv, int newv) {
erase(seg[u].rt, oldv); insert(seg[u].rt, newv);
if (seg[u].l == seg[u].r) return;
int mid = (seg[u].l + seg[u].r) >> 1;
if (pos <= mid) modify(u<<1, pos, oldv, newv);
else modify(u<<1|1, pos, oldv, newv);
}
// 區間查詢示例:排名
int queryRank(int u, int L, int R, int x) {
if (seg[u].l == L && seg[u].r == R) return rank(seg[u].rt, x);
int mid = (seg[u].l + seg[u].r) >> 1;
if (R <= mid) return queryRank(u<<1, L, R, x);
if (L > mid) return queryRank(u<<1|1, L, R, x);
return queryRank(u<<1, L, mid, x) + queryRank(u<<1|1, mid+1, R, x);
}
[0, 1e8],二分上界設 1e9。k 可能為負數,Treap 需支援負值。new 開銷;rand() 種子固定便於調試。4*MAXN,Treap 節點 MAXN * 20 通常足夠。