雅禮集訓 2017 Day7 事情的相似度

2022-05-23 21:18:09 字數 1290 閱讀 8157

點此看題

字尾自動機亂殺。

他問的是字首之間的最長字尾,我們對正串建出字尾自動機,然後把字首在自動機上面打上標記。根據字尾自動機的性質,最長字尾就是兩個字首在 \(\tt parent \;tree\) 上 \(\tt lca\) 的 \(len\)

對於乙個字首對 \((l,r)\) ,那麼他可以對 \(l\leq l,r\leq r\) 的詢問 \((l,r)\) 產生貢獻。因為是 \(\tt lca\) ,所以可以想到通過樹上啟發式合併找出這些字首對,那麼我們在合併子樹的時候就要考慮子樹之間新產生的點對。

貌似這樣字首對的數量是 \(o(n^2)\) 的,合併的時候我們只需要找最接近的字首,因為貢獻都是一樣的,但是找最接近的能貢獻到的是最多的,所以數量是 \(o(n\log n)\),用 \(\tt set\) 維護啟發式合併。

那麼時間複雜度 \(o(n\log^2 n)\),最後算貢獻的時候本質上是乙個二維偏序,所以直接排序就行了。

#include #include #include #include using namespace std;

const int m = 200005;

int read()

while(c>='0' && c<='9')

return x*f;

}int n,m,k,tot,cnt,last,bit[m],f[m],ans[m];char t[m];

sets[m];

struct edge

}e[2*m];

struct node

a[m];

struct zxy

; if(nxt!=s[u].end()) p[++k]=zxy;

s[u].erase(*it);

} for(it=s[v].begin();it!=s[v].end();it++)

s[u].insert(*it); }}

int lowbit(int x)

void add(int x,int y)

int ask(int x)

signed main()

for(int i=2;i<=cnt;i++)

dfs(1,0);

sort(p+1,p+1+k);

for(int i=1;i<=m;i++)

; }sort(q+1,q+1+m);

for(int i=1,j=1;i<=m;i++)

for(int i=1;i<=m;i++)

printf("%d\n",ans[i]);

}

雅禮集訓2017Day7事情的相似度

bitset幫助離線合併實現o n w 然後暴力就可以在n 100000時為所欲為 其實還是有點思想,從大到小列舉height值,這樣每次涉及到的問題的答案一定是height 另外脫機會mle?那就分兩次離唄。沒有什麼是一次離線解決不了的,如果有,那就兩次。從height大到小更新可以簡化轉移,因為...

雅禮集訓 2017 Day7 事情的相似度

text 處理了一下排版問題,以及新增 rm lct 做法。如果沒有原題測試,還不知道這道題還要被咕多久.本來就已經咕了乙個寒假了.傳送門 to loj 最長公共字尾,很難不讓人想到 tt sam 的 text 因為在 text 上有 兩個串的最長公共字尾,即為他們所代表的點在樹上的 lca 對應的...

雅禮集訓 2017 價

傳送門 乙個不太顯然的最小割做法。我們這麼連邊 源點向藥物連 infty p i 容量的邊,藥物向它對應的藥材連 infty 容量的邊,藥材向匯點連 infty 容量的邊。用源點的流量減去最小割,再負回來就可以求出答案了。怎麼理解呢?割掉一條邊表示不選其對應的藥物或藥材,我們發現最後的方案一定是完美...