首页 > 代码库 > bzoj4104 [Thu Summer Camp 2015]解密运算

bzoj4104 [Thu Summer Camp 2015]解密运算

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4104

【题解】

脑洞+找规律做出来的。。

我用样例作为说明吧

样例给了我们这个

A
A
A
C
.
A
B

看起来没啥用

这是那个矩阵的最后一列对吧。

第一列是什么呢?我们都知道,按字典序排列。

.
A
A
A
A

C

由于这是一个环,所以第一个字母和最后一个字母是相邻的。换句话说,我们只要知道第一个字母和最后一个字母的对应关系,我们就能知道环长什么样了。

问题在于。有很多个重复的数,我们怎么知道对应的顺序呢?

如果我要比较A的顺序,我们不妨画个图

_ _ _ _ _ _ A
_ _ _ _ _ _ A
_ _ _ _ _ _ A
_ _ _ _ _ _ C
_ _ _ _ _ _ .
_ _ _ _ _ _ A 
_ _ _ _ _ _ B

如果我把第一个A作为首位,和第二个A作为首位,哪个字典序大?

要明确的是,第一个A的前面6个位置组成的字符串一定小于第二个A前面6个位置组成的字符串

所以把A提前,仍然是第一个A作为首位的字符串<第二个A作为首位的字符串。

我们就可以把A标号,然后进行对应了。

.   _____A1
A1_____A2
A2_____A3
A3_____C
A4_____.
B _____A4
C _____B

这样就非常好了,然后我们从"."开始,把"______"看成边,沿着边走一遍就得到了这个环。

稍微看下就知道要从那个方向开始走了。

然后就解决了这道题了。

技术分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, m, v[M], nx[M], beg;
struct pa {
    int x, pos;
    pa() {}
    pa(int x, int pos) : x(x), pos(pos) {}
    friend bool operator < (pa a, pa b) {
        return a.x < b.x || (a.x == b.x && a.pos < b.pos);
    }
}p[M];

int main() {
    cin >> n >> m;
    for (int i=1; i<=n+1; ++i) {
        scanf("%d", &v[i]);
        p[i] = pa(v[i], i);
        if(v[i] == 0) beg = i;
    }
    sort(p+1, p+n+2);
    for (int i=1; i<=n+1; ++i) 
        nx[i] = p[i].pos;
    int cur = beg;
    while(nx[cur] != beg) {
        cur = nx[cur];
        printf("%d ", v[cur]);
    }
    return 0;
}
View Code

 

bzoj4104 [Thu Summer Camp 2015]解密运算