http://poj.org/problem?id=3581
这题说是给了N个数字组成的序列A1 A2 ..An 其中A1 大于其他的数字 , 现在要把序列分成三段并将每段分别反转求最小字典序
以后还是老老实实用基数排序 用sort wa 了 一晚
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <vector> using namespace std; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ const int maxn =200005; struct SuffixArry { int c[maxn*2],t[maxn*2],t1[maxn*2],sa[maxn*2]; void build(int n,int m,int *S) { int *x=t,*y=t1,i; for( i=0; i<m; i++)c[i]=0; for( i=0; i<n; i++)c[x[i]=S[i] ]++; for( i=1; i<m; i++)c[i]+=c[i-1]; for( i=n-1; i>=0; i--)sa[ --c[ x[i] ] ]=i; int p; for(int k=1; k<=n; k<<=1 ) { p=0; for( i = n-k; i<n; i++)y[p++]=i; for( i=0; i<n; i++) if(sa[i]>=k)y[p++]=sa[i]-k; for( i=0; i<m; i++)c[ i ] =0 ; for( i=0 ; i<n; i++ )c[ x[ y[i] ] ]++; for( i=1; i<m; i++) c[i]+=c[i-1]; for( i=n-1; i>=0; i--) sa[--c[ x[ y[i] ] ] ]=y[i]; swap(x,y); p=1; x[ sa[ 0 ] ] = 0; for(int i=1; i<n; i++) x[ sa[i] ] = y[ sa[i] ]== y[ sa[i-1] ]&& y[ sa[i]+k ]==y[sa[i-1]+k]?p-1:p++; if(p>=n)break; m=p; } } void clear(){ memset(t,-1,sizeof(t)); memset(t1,-1,sizeof(t1)); } }T; int A[maxn],B[maxn],C[maxn],rev[maxn*2]; void revercopy(int *a, int *b, int len) { for(int i=0; i<len; i++) { b[i]=a[len-1-i]; } } void rever(int *a, int len) { for(int i=0; i<len/2; i++ ) { int t= a[i]; a[i]=a[len-1-i]; a[len-1-i]=t; } } int main(int argc, char *argv[]) { int n; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&A[i]); B[i]=A[i]; } sort(B,B+n); int L=unique(B,B+n)-B; for(int i=0; i<n; i++) { C[i]=lower_bound(B,B+L,A[i])-B; } int p1; T.clear(); revercopy(C,rev,n); T.build(n,L,rev); for(int i=0; i<n; i++) { p1 = n-T.sa[i]; if(p1>0&&n-p1>=2)break; } if(p1<1||n-p1<2)while(true){}; int m= n-p1; revercopy(C+p1,rev,m); //for(int i=0; i<m; i++)printf("%d ",rev[i]); revercopy(C+p1,rev+m,m);//for(int i=0; i<m*2; i++)printf("%d ",rev[i]); T.build(m*2,L,rev); int p2; for(int i=0; i<m*2; i++) { p2 = p1 + m - T.sa[ i ]; if(p2>p1&&n-p2>=1)break; } if(p2<=p1||n-p2<1)while(true){ }; rever(A,p1); rever(A+p1,p2-p1); rever(A+p2,n-p2); for(int i=0; i<n; i++) printf("%d\n",A[i]); return 0; }
时间: 2024-12-28 04:14:21