1. 程式人生 > >bzoj4104 [Thu Summer Camp 2015]解密運算

bzoj4104 [Thu Summer Camp 2015]解密運算

sort sign include 走了 space friend def static none

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=4104

【題解】

腦洞+找規律做出來的。。

我用樣例作為說明吧

樣例給了我們這個

A
A
A
C
.
A
B

看起來沒啥用

這是那個矩陣的最後一列對吧。

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

.
A
A
A
A
B
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]解密運算