BZOJ4516: [Sdoi2016]生成魔咒
生活随笔
收集整理的這篇文章主要介紹了
BZOJ4516: [Sdoi2016]生成魔咒
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
BZOJ4516: [Sdoi2016]生成魔咒
Description
魔咒串由許多魔咒字符組成,魔咒字符可以用數(shù)字表示。 例如可以將魔咒字符 1、2 拼湊起來(lái)形成一個(gè)魔咒串 [1,2]。 一個(gè)魔咒串 S 的非空字串被稱為魔咒串 S 的生成魔咒。 例如 S=[1,2,1] 時(shí),它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五種。 S=[1,1,1] 時(shí),它的生成魔咒有 [1]、[1,1]、[1,1,1] 三種。 最初 S 為空串。共進(jìn)行 n 次操作,每次操作是在 S 的結(jié)尾加入一個(gè)魔咒字符。 每次操作后都需要求出,當(dāng)前的魔咒串 S 共有多少種生成魔咒。Input
第一行一個(gè)整數(shù) n。 第二行 n 個(gè)數(shù),第 i 個(gè)數(shù)表示第 i 次操作加入的魔咒字符。 1≤n≤100000。 用來(lái)表示魔咒字符的數(shù)字 x 滿足 1≤x≤10^9Output
輸出 n 行,每行一個(gè)數(shù)。第 i 行的數(shù)表示第 i 次操作后 S 的生成魔咒數(shù)量
Sample Input
71 2 3 3 3 1 2
Sample Output
13
6
9
12
17
22
題解Here! 據(jù)說(shuō)這題可以被$SAM$秒殺,然而本蒟蒻只會(huì)$SA$。。。 題目要求出每一個(gè)前綴本質(zhì)不同的后綴的個(gè)數(shù)。 那么我們可以把原序列倒過(guò)來(lái),然后實(shí)際上就是對(duì)于每一個(gè)后綴求與其它后綴不重復(fù)的前綴個(gè)數(shù),也即是后綴長(zhǎng)度減去$height$。 求出某一個(gè)后綴對(duì)答案的貢獻(xiàn)之后,他不應(yīng)該停留在元序列中對(duì)后續(xù)答案的求解產(chǎn)生影響,所以應(yīng)該把它刪除。 這個(gè)可以用平衡樹來(lái)完成。 但是考慮到每一個(gè)位置只與前后有關(guān),我們可以用鏈表來(lái)代替。 還有,要離散化。。。 附代碼: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define MAXN 100010 using namespace std; int n; int val[MAXN],num[MAXN],SBT_front[MAXN],SBT_next[MAXN]; long long ans[MAXN]; int top,sa[MAXN],rk[MAXN],height[MAXN],tax[MAXN],tp[MAXN]; inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w; } void radixsort(){for(int i=0;i<=top;i++)tax[i]=0;for(int i=1;i<=n;i++)tax[rk[i]]++;for(int i=1;i<=top;i++)tax[i]+=tax[i-1];for(int i=n;i>=1;i--)sa[tax[rk[tp[i]]]--]=tp[i]; } void suffixsort(int x){top=x;for(int i=1;i<=n;i++){rk[i]=val[i];tp[i]=i;}radixsort();for(int w=1,p=0;p<n;top=p,w<<=1){p=0;for(int i=1;i<=w;i++)tp[++p]=n-w+i;for(int i=1;i<=n;i++)if(sa[i]>w)tp[++p]=sa[i]-w;radixsort();swap(tp,rk);rk[sa[1]]=p=1;for(int i=2;i<=n;i++)rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;} } void getheight(){for(int i=1,j,k=0;i<=n;i++){if(k)k--;j=sa[rk[i]-1];while(val[i+k]==val[j+k])k++;height[rk[i]]=k;} } void work(){for(int i=1;i<=n;i++){SBT_front[i]=i-1;SBT_next[i]=i+1;}for(int i=1;i<=n;i++){int now=n-i+1-max(height[rk[i]],height[SBT_next[rk[i]]]);ans[i]=(long long)now;height[SBT_next[rk[i]]]=min(height[rk[i]],height[SBT_next[rk[i]]]);height[rk[i]]=0;if(rk[i]!=1)SBT_next[SBT_front[rk[i]]]=SBT_next[rk[i]];SBT_front[SBT_next[rk[i]]]=SBT_front[rk[i]];}for(int i=n;i>=1;i--)ans[i]+=ans[i+1];for(int i=n;i>=1;i--)printf("%lld\n",ans[i]); } void init(){n=read();for(int i=1;i<=n;i++)num[i]=val[n-i+1]=read();sort(num+1,num+n+1);int k=unique(num+1,num+n+1)-num-1;for(int i=1;i<=n;i++)val[i]=lower_bound(num+1,num+k+1,val[i])-num;suffixsort(k+1);getheight(); } int main(){init();work();return 0; }
?
轉(zhuǎn)載于:https://www.cnblogs.com/Yangrui-Blog/p/9447643.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ4516: [Sdoi2016]生成魔咒的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 1 微信公众号开发 服务器配置 有什么用
- 下一篇: 【终极算法】从阿尔法狗元(AlphaGo