码迷,mamicode.com
首页 > 编程语言 > 详细

[后缀数组+贪心] poj 3518 Sequence

时间:2015-04-14 12:57:36      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给定一个数列,第一项比其他任何项都要大,要求分成三份,不能为空,分成三份后,再翻转,求最小的序列。

思路:

首先是把串map,然后反转一下。

接着求一下sa,很明显第一次切的地方一定是sa[i]>1的第一个最小的位置。

接着就是第二刀了。

很明显不能直接再找sa[i]第二小的。

因为第一刀之所以能那样切是因为数列的第一个数一定比其他都大。

那么我们需要把剩下的串复制一份拼接到后面去,再求一次sa。

为什么要这样做呢?

是因为我们要找切的地方,切完之后就肯定与前面的相连,所以找到到最小的。

就连起来找。

这里给几组样例:

7
10 0 2 2 2 2 1

7
10 0 2 2 2 2 3

最后特别注意下,这题多实例会WA,必须单实例。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#include"vector"
#define ll long long
using namespace std;
#define N 212054
int wa[N],wb[N],wv[N],wws[N];
int sa[N],ra[N],height[N];
int fuck[N],kx[N];
int v[N];
int cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int n,int m)
{
    int i,j,p,*x=wa,*y=wb;
    for(i=0; i<m; i++) wws[i]=0;
    for(i=0; i<n; i++) wws[x[i]=v[i]]++;
    for(i=1; i<m; i++) wws[i]+=wws[i-1];
    for(i=n-1; i>=0; i--) sa[--wws[x[i]]]=i;
    for(j=1,p=1; p<n; j*=2,m=p)
    {
        for(i=n-j,p=0; 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++) wws[i]=0;
        for(i=0; i<n; i++) wws[wv[i]]++;
        for(i=1; i<m; i++) wws[i]+=wws[i-1];
        for(i=n-1; i>=0; i--) sa[--wws[wv[i]]]=y[i];
        for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
    }
    return ;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%d",&fuck[i]);
    memcpy(v,fuck,sizeof(fuck));
    sort(fuck,fuck+n);
    map<int,int>mp;
    for(int i=0; i<n; i++)
    {
        mp[fuck[i]]=i+5;
        kx[i+5]=fuck[i];
    }
    for(int i=0; i<=(n-1)/2; i++) swap(v[i],v[n-1-i]);
    for(int i=0; i<n; i++) v[i]=mp[v[i]];
    v[n]=0;
    da(n+1,n+10);
    int f1,f2;
    for(int i=1; i<=n; i++)
    {
        if(sa[i]>1)
        {
            f1=sa[i];
            break;
        }
    }
    for(int i=f1; i<n; i++) printf("%d\n",kx[v[i]]);
    for(int i=0;i<f1;i++) v[i+f1]=v[i];
    v[2*f1]=0;
    da(2*f1+1,n+10);
    for(int i=1;i<=2*f1;i++)
    {
        if(sa[i]>0 && sa[i]<f1)
        {
            f2=sa[i];
            break;
        }
    }
    for(int i=f2; i<f1; i++) printf("%d\n",kx[v[i]]);
    for(int i=0; i<f2; i++) printf("%d\n",kx[v[i]]);
    puts("");
    return 0;
}


[后缀数组+贪心] poj 3518 Sequence

标签:

原文地址:http://blog.csdn.net/wdcjdtc/article/details/45040113

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!