poj 3581 Sequence
http://poj.org/problem?id=3581
题意:给一个整数序列,要求划分成三个连续的子序列,同时将子序列反序,使得最后得到的序列的子典序最小。
思路:对于这个序列,很明显,每个整数最后都要反序一次,所以可以先把原来的序列反序,这样问题就可以转化成在一个序列里,划分三个连续的子序列,按一定的顺序输出这个子序列,使得最后的序列字典序最小。先考虑第一个序列,因为原序列的第一个整数是最大的,也就是反序列中最后一个元素是最大的,所以第一个序列就是反序列后的最小后缀。求第二个序列的时候因为没有了第一个序列的最大元素,所以不能直接求最小后缀。这时可以先把第一个序列割出来,然后重复一次剩下的序列,再求一次最小后缀就是第二个序列了。
PS:这个题的输入文件中有多余的输入~~~

#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") using namespace std; const int maxn = 401000; int wn[maxn],wa[maxn],wb[maxn],wv[maxn],a[maxn],sa[maxn],rank[maxn],height[maxn],as[maxn]; char r[maxn]; int Max(int x,int y){return x>y?x:y;} int Min(int x,int y){return x>y?y:x;} int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i = 0; i < m; ++ i) wn[i] = 0; for(i = 0; i < n; ++ i) wn[x[i]=r[i]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[x[i]]] = i; for(p = 1,j = 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 < m; ++ i) wn[i] = 0; for(i = 0; i < n; ++ i) wn[wv[i]=x[y[i]]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[wv[i]]] = y[i]; for(t = x,x = y,y = t,x[sa[0]] = 0,p=1,i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } int main() { int n,i,s,t; scanf("%d",&n); set<int>bs; set<int>::iterator pos; map<int,int>cs; for(int i = 0; i < n; ++ i){ scanf("%d",as+i); bs.insert(as[i]); } pos = bs.begin(); for(int i = 0; pos != bs.end(); ++ pos,i++) cs[*pos] = i; for(int i = n - 1,j = 0; i > -1; -- i) a[j++] = cs[as[i]]+1; a[n] = 0; da(a,sa,n+1,cs[as[0]]+2); for(i = 1; i <= n; ++ i) if(sa[i]>1) break; s = sa[i]; for(i = 0; i < s; ++ i) a[s+i] = a[i]; t = s * 2 + 1; s = n - s - 1; a[t-1] = 0; da(a,sa,t,cs[as[0]]+2); for(i = 1; i < t; ++ i)if(sa[i]<t/2&&sa[i]>0)break; t = t / 2; t = t - sa[i] + s; for(i = s; i >= 0; -- i)printf("%d\n",as[i]); for(i = t; i > s; -- i)printf("%d\n",as[i]); for(i = n - 1; i > t; --i)printf("%d\n",as[i]); return 0; }