cao 還有二分字典序這種操作。。。。
問題性質顯然滿足二分性,但是我們只能對數進行二分,但是如果可以根據乙個數確定乙個字串就好了。
用sa可以實現,根據乙個整數x,可以在\(o(\min (n,ans))\),得到字典序在所有子串中x位的那個串具體是什麼。
二分完之後就是貪心了,從後往前列舉每個位置要不要斷開,現在問題就變成了乙個母串中有兩個子串要比較字典序,也是sa+倍增就行了。
貪心時可以發現,直接在當前位置的後面斷開最優,因為這樣分出來的字典序更小。
//@winlere
#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn=1e5+5;
void suf_sort(char*str,int*rk,int*sa,int*h,int n)
for(int t=1;t<=n;++t) ++b[rk[t]];
for(int t=1;t<=m;++t) b[t]+=b[t-1];
for(int t=n;t;--t) sa[b[rk[temp[t]]]--]=temp[t];
memset(b+1,0,m<<2); memcpy(temp+1,rk+1,n<<2);
rk[sa[1]]=1;
for(int t=2;t<=n;++t)
rk[sa[t]]=temp[sa[t]]==temp[sa[t-1]]&&temp[sa[t]+l]==temp[sa[t-1]+l]?rk[sa[t-1]]:rk[sa[t-1]]+1;
m=rk[sa[n]];
} for(int t=1,p=0;t<=n;++t)
}int rk[maxn],sa[maxn],st[21][maxn],lg[maxn],n,k;
char c[maxn];
pairgetkth(ll k)
int _que(int l,int r)
bool isnotmore(paira,pairb)
bool chek(ll mid)
return ret<=k;
}int main()
BZOJ4310 跳蚤 字尾陣列 二分
很久很久以前,森林裡住著一群跳蚤。一天,跳蚤國王得到了乙個神秘的字串,它想進行研究。首先,他會把串 分成不超過 k 個子串,然後對於每個子串 s,他會從s的所有子串中選擇字典序最大的那乙個,並在選出來的k個子串中選擇字典序最大的那乙個。他稱其為 魔力串 現在他想找乙個最優的分法讓 魔力串 字典序最小...
BZOJ4310 跳蚤(字尾陣列 二分答案)
傳送門 dar kbzo jdarkbzoj darkbz oj上題面有誤,應該是最大的最小 考慮二分這個最小的串x xx的排名k kk那麼也就是說所有排名比這個大的一定要被切開 考慮乙個字尾s p n s p,n s p,n 如果l cp s p n x 0 lcp s p,n x 0 lcp s...
BZOJ4310 跳蚤(字尾陣列 二分答案)
注意到答案一定是原串的子串,於是考慮造出sa,二分答案是第幾小的子串。第k小子串很容易在sa上求出。之後計算使他成為最大子串至少要在幾個位置切割,對每個字典序比答案大的字尾,找到所有合法切割位置 求lcp即可 就轉化成了選最少的點使每個區間都包含至少乙個點的經典問題。include include ...