BZOJ3682 Phorni 字尾平衡樹

2021-09-08 20:32:48 字數 2235 閱讀 8220

傳送門

字尾平衡樹模板題

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

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

可以用二分加hash,複雜度 log

2n

log^2n

log2

n 插入

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

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

像這樣分配權值

給樹上每個子樹乙個實數權值區間 [l,

r]

[l,r]

[l,r

],這個點權值為 mid

=l+r

2mid=\frac

mid=2l

+r​左子樹 [l,

mid]

[l,mid]

[l,mid

] 右子樹 [mi

d,r]

[mid,r]

[mid,r

]

那麼可以做到 o(1

)o(1)

o(1)

比較只需要選擇乙個樹高 log

loglo

g 的樹(treap/替罪羊樹)使得滿足精度要求即可

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

# include

using

namespace std;

typedef

long

long ll;

const

intmaxn

(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)

intbuild

(int l,

int r,

double vl,

double vr)

intrebuild

(int x,

double vl,

double vr)

inline

intcompare

(int x,

int y)

intinsert

(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));

}return0;

}

BZOJ3682 Phorni 字尾平衡樹

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

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...