BZOJ3682 Phorni 字尾平衡樹

2022-05-07 18:39:11 字數 1511 閱讀 3503

傳送門

字尾平衡樹模板題

用平衡樹維護每乙個字尾的排名

關鍵在於查詢兩個字尾的大小

可以用二分加hash,複雜度 \(log^2n\) 插入

或者:每次前面插入乙個字元,先比較兩個字尾第乙個字元的大小

而後面的大小我們已經在平衡樹上維護好了

像這樣分配權值

給樹上每個子樹乙個實數權值區間 \([l,r]\),這個點權值為 \(mid=\frac\)

左子樹 \([l,mid]\) 右子樹 \([mid,r]\)

那麼可以做到 \(o(1)\) 比較

只需要選擇乙個樹高 \(log\) 的樹(treap/替罪羊樹)使得滿足精度要求即可

最後用線段樹維護一下每個幻影的最小的字尾

# include using namespace std;

typedef long long ll;

const int maxn(1e6 + 5);

const double alpha(0.75);

int ls[maxn], rs[maxn], rt, tot, size[maxn], que[maxn], cnt;

double val[maxn];

int mn[maxn << 1], id[maxn], n, m, p[maxn], pos[maxn];

char s[maxn];

void dfs(int u)

int build(int l, int r, double vl, double vr)

int rebuild(int x, double vl, double vr)

inline int compare(int x, int y)

int insert(int &x, double vl, double vr, int ps)

if (alpha * size[x] < max(size[ls[x]], size[rs[x]])) x = rebuild(x, vl, vr);

if (compare(ps, pos[x])) ret = insert(ls[x], vl, midv, ps);

else ret = insert(rs[x], midv, vr, ps);

size[x] = size[ls[x]] + size[rs[x]] + 1;

return ret;

}void modify(int x, int l, int r, int ps)

}int query(int x, int l, int r, int ql, int qr)

return ret;

}int main()

else if (op == 'c')

else scanf("%d%d", &l, &r), printf("%d\n", ans = query(1, 1, n, l, r));

} return 0;

}

BZOJ3682 Phorni 字尾平衡樹

傳送門 字尾平衡樹模板題 用平衡樹維護每乙個字尾的排名 關鍵在於查詢兩個字尾的大小 可以用二分加hash,複雜度 log 2n log 2n log2 n 插入 或者 每次前面插入乙個字元,先比較兩個字尾第乙個字元的大小 而後面的大小我們已經在平衡樹上維護好了 像這樣分配權值 給樹上每個子樹乙個實數...

bzoj 1692 字尾陣列

將乙個字串進行如下操作 每次拿去首或尾,放在新字串尾,問新字串字典序最小的情況。直覺貪心,但情況複雜。可以用字尾陣列,每次比較當前剩餘串正序和倒序哪種字典序小,可以如下構建 abcd abcd0dcba include include include include include include ...

bzoj 2119 字尾陣列

題意 給乙個串,求形如aba,其中b的長度為m,a的長度不限的子串的數量。求正串反串的字尾陣列和對於h的rmq。列舉a串長度len,對於每個長度為len的區間處理在這段區間開始的子串個數。每隔len列舉i,然後用rmq求i和i len m的最長公共字首字尾l,r。統計長度為len的在區間 i l 1...