bzoj 4278 [ONTAK2015]Tasowanie——后缀数组
Posted narh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4278 [ONTAK2015]Tasowanie——后缀数组相关的知识,希望对你有一定的参考价值。
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4278
因为每次要放后缀较小的那个,所以把两个序列放在一起排序吧。改一改模板。
其实要改的地方就是让后面序列那部分不要在倍增的时候更新前面序列那部分。
考虑 4 和 43 ,应该是 43 比 4 小;因为放了单独的 4 的话就只能放 43 ,而放了 43 的 4 的话可以放 3 再放单独的 4 。
即,前缀相等的话短的比较大、长的比较小。把 n-k+1 ~ n 的那个赋值放在 if( sa[i] > k ) 的赋值后面就行了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=4e5+5; int n,m,tn,a[N],sa[N],tp[N],rk[N],tx[N]; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)fx=0;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar(); return fx?ret:-ret; } void Rsort(int nm) { for(int i=1;i<=nm;i++)tx[i]=0; for(int i=1;i<=tn;i++)tx[rk[i]]++; for(int i=2;i<=nm;i++)tx[i]+=tx[i-1]; for(int i=tn;i;i--)sa[tx[rk[tp[i]]]--]=tp[i]; } void work() { int nm=1000; for(int i=1;i<=tn;i++)tp[i]=i,rk[i]=a[i]; Rsort(nm); for(int k=1;k<=tn;k<<=1) { int tot=0; for(int i=1,j=n+k;i<=tn;i++) if((sa[i]<=n&&sa[i]>k)||(sa[i]>j)) tp[++tot]=sa[i]-k; for(int i=max(1,n-k+1);i<=n;i++)tp[++tot]=i;//max//here after ... for(int i=max(n+1,tn-k+1);i<=tn;i++)tp[++tot]=i; Rsort(nm); swap(rk,tp);nm=1;rk[sa[1]]=1; for(int i=2,u,v;i<=tn;i++) { u=sa[i]+k;v=sa[i-1]+k; if((sa[i]<=n&&u>n)||(sa[i]>n&&u>tn))u=0; if((sa[i-1]<=n&&v>n)||(sa[i-1]>n&&v>tn))v=0; rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[u]==tp[v])?nm:++nm;//rk[sa[i]] } if(nm==tn)break; } } int main() { n=rdn();for(int i=1;i<=n;i++)a[i]=rdn(); m=rdn();tn=n+m;for(int i=n+1;i<=tn;i++)a[i]=rdn(); work(); int p0=1,p1=n+1; for(int i=1;i<=tn;i++) { if(rk[p0]<rk[p1])printf("%d ",a[p0]),p0++; else printf("%d ",a[p1]),p1++; if(p0>n||p1>tn)break; } if(p0<=n)for(;p0<=n;p0++)printf("%d ",a[p0]); if(p1<=tn)for(;p1<=tn;p1++)printf("%d ",a[p1]); puts(""); return 0; }
以上是关于bzoj 4278 [ONTAK2015]Tasowanie——后缀数组的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4278 [ONTAK2015]Tasowanie——后缀数组
BZOJ 4245: [ONTAK2015]OR-XOR 贪心