Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 6305 | Accepted: 1364 | |
Case Time Limit: 2000MS |
Description
Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.
The alphabet order is defined as follows: for two sequence {A1, A2, ..., An} and {B1, B2, ..., Bn}, we say {A1, A2, ..., An} is smaller than {B1, B2, ..., Bn} if and only if there exists such i ( 1 ≤ i ≤ n) so that we have Ai < Bi and Aj = Bj for each j < i.
Input
The first line contains n. (n ≤ 200000)
The following n lines contain the sequence.
Output
output n lines which is the smallest possible sequence obtained.
Sample Input
5 10 1 2 3 4
Sample Output
1 10 2 4 3
Hint
{10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}
题意:给你n个数(保证第一个数字大于这n个数的其他任何数字),让你把这n个数分成三份,每一份必须至少含有一个数字,然后把这三份的数字倒置,再把这三部分拼成一个串,并且要使得这个字符串的字典序最小。
思路:先考虑第一段,因为第一个数字大于这n个数的其他任何数字,所以我们可以把字符串取反,然后找到字典序最小的后缀作为第一段,还要保证后缀的长度不超过n-2,如果超过后面就不能分成两个串(如果这里不懂可以画一下).然后我们把剩下的字符串取出来,表示成长度为m的a[]数组,接下来的问题就变为怎么样找到一个分割点k,使得a[0],a[1],...a[k]的反串和a[k+1],a[k+2]...a[m-1]的反串连接起来的串的字典序最小,我们转化一下就变为求分割点k,使得a[k],a[k-1]...a[0],a[m-1],a[m-2]...a[k+1]的字典序最小,我们发现,a[k],a[k-1]...a[0],a[m-1],a[m-2]...a[k+1]是a[m-1]...a[0]a[m-1]...a[0]的子串,所以我们只要把串a反一下,然后再扩展一倍,求出最小字典序的后缀就行了,这里要注意后缀的起始位置要大于0,小于m。
ps:这题不能用多组数据输入,会wa,也是醉了。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<string> #include<bitset> #include<algorithm> using namespace std; #define lson th<<1 #define rson th<<1|1 typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 400050 int sa[maxn],a[maxn],b[maxn],pos[maxn]; int wa[maxn],wb[maxn],wv[maxn],we[maxn]; int rk[maxn],height[maxn]; int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void build_sa(int *r,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++)we[i]=0; for(i=0;i<n;i++)we[x[i]=r[i]]++; for(i=1;i<m;i++)we[i]+=we[i-1]; for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p){ for(p=0,i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<n;i++)wv[i]=x[y[i]]; for(i=0;i<m;i++)we[i]=0; for(i=0;i<n;i++)we[wv[i]]++; for(i=1;i<m;i++)we[i]+=we[i-1]; for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void calheight(int *r,int n) { int i,j,k=0; for(i=1;i<=n;i++)rk[sa[i]]=i; for(i=0;i<n;height[rk[i++] ]=k){ for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++); } } int calmin(int n) { int minx=inf,i; int weizhi=-1; for(i=2;i<n;i++){ if(rk[i]<minx){ minx=rk[i]; weizhi=i; } } return weizhi; } int c[maxn],cnt; int d[maxn]; int main() { int m,i,j,tot,n,weizhi,mm; scanf("%d",&n); tot=0; for(i=0;i<n;i++){ scanf("%d",&a[i]); pos[++tot]=a[i]; } sort(pos+1,pos+1+tot); tot=unique(pos+1,pos+1+tot)-pos-1; for(i=0;i<n;i++){ a[i]=lower_bound(pos+1,pos+1+tot,a[i])-pos; b[n-1-i]=a[i]; } b[n]=0; build_sa(b,n+1,200010); calheight(b,n); weizhi=calmin(n); cnt=0; for(i=weizhi;i<n;i++){ c[cnt++]=pos[b[i] ]; } m=0; for(i=0;i<weizhi;i++){ d[m++]=b[i]; } for(i=0;i<m;i++){ d[i+m]=d[i]; } mm=m*2; d[mm]=0; build_sa(d,mm+1,200010 ); calheight(d,mm); int minx=inf; weizhi=-1; for(i=1;i<m;i++){ if(rk[i]<minx){ minx=rk[i]; weizhi=i; } } for(i=weizhi;i<m;i++){ c[cnt++]=pos[d[i] ]; } for(i=0;i<weizhi;i++){ c[cnt++]=pos[d[i] ]; } for(i=0;i<cnt;i++){ printf("%d\n",c[i]); } }