poj 3581 Sequence

http://poj.org/problem?id=3581

题意:给一个整数序列,要求划分成三个连续的子序列,同时将子序列反序,使得最后得到的序列的子典序最小。

思路:对于这个序列,很明显,每个整数最后都要反序一次,所以可以先把原来的序列反序,这样问题就可以转化成在一个序列里,划分三个连续的子序列,按一定的顺序输出这个子序列,使得最后的序列字典序最小。先考虑第一个序列,因为原序列的第一个整数是最大的,也就是反序列中最后一个元素是最大的,所以第一个序列就是反序列后的最小后缀。求第二个序列的时候因为没有了第一个序列的最大元素,所以不能直接求最小后缀。这时可以先把第一个序列割出来,然后重复一次剩下的序列,再求一次最小后缀就是第二个序列了。

PS:这个题的输入文件中有多余的输入~~~

View Code
#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;
}

posted on 2012-07-09 11:05  aigoruan  阅读(231)  评论(0)    收藏  举报

导航