bzoj4104: [Thu Summer Camp 2015]解密运算

挖掘性质题,还是脑洞不够大只会40pt

首先可以发现,每个位置的字母都会放在给出的子串结尾有且仅有一次(废话)

然后据此就可以找出这个串是由哪些字母组成的了,排一波序就知道对于给出的子串的第一位置是啥了

既知道最后一个位置,又知道第一个位置,这两个位置是相邻的,确认两个字母的关系,假如互不相同就做完了

现在问题在于如何比较两个第一位置相同的子串谁在谁的前面

我的想法就此停滞。。。。。。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%分割线%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

我们可以发现,每个子串0以及它后面的一段是没有用的,对所有的子串排完序以后搞出来的顺序就是sa数组,我们不知道sa的具体值,但输入第i行给出的就是排名为i的后缀的前一个字母是什么,反过来说,我们可以知道某一个字母的后面是排名为i的后缀!这个产生了巨大的作用

接着是排序步骤,我们可以理解为把最后一个字母拉出来排序,首先第一关键字就是这个字母本身,第二关键字就是这个字母后面的后缀!

好妙啊

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int _=1e2;
const int maxn=2*1e5+_;

pair<int,int>a[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++)
        scanf("%d",&a[i].first),a[i].second=i;
    sort(a,a+n+1);
    
    int now=a[0].second;
    for(int i=1;i<n;i++)
    {
        printf("%d ",a[now].first);
        now=a[now].second;
    }
    printf("%d\n",a[now].first);
    
    return 0;
}

 

posted @ 2019-02-21 21:33  AKCqhzdy  阅读(76)  评论(0编辑  收藏  举报