[BZOJ2882]工艺
Posted Elder_Giang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2882]工艺相关的知识,希望对你有一定的参考价值。
2882: 工艺
Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1085 Solved: 469 [Submit][Status][Discuss]Description
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。
Input
第一行两个整数n,代表方块的数目。
第二行n个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。
Output
一行n个整数,代表最美观工艺品从左到右瑕疵度的值。
Sample Input
10
10 9 8 7 6 5 4 3 2 1
Sample Output
1 10 9 8 7 6 5 4 3 2
HINT
这题可以通过把串复制一遍接在后面,然后SA做
#include <cstdio> #include <algorithm> using namespace std; inline int readint(){ int n = 0; char ch = getchar(); while(ch < ‘0‘ || ch > ‘9‘) ch = getchar(); while(ch <= ‘9‘ && ch >= ‘0‘){ n = (n << 3) + (n << 1) + ch - ‘0‘; ch = getchar(); } return n; } const int maxn = 300000 + 10; int n, m; int s[maxn * 2], num[maxn], ref[maxn]; inline bool cmp(int *arr, int x, int y, int l){ return arr[x] == arr[y] && arr[x + l] == arr[y + l]; } int sa[maxn * 2], rank[maxn * 2]; int tax[maxn * 2], tp[maxn * 2]; inline void Rsort(){ for(int i = 0; i <= m; i++) tax[i] = 0; for(int i = 1; i <= n; i++) tax[rank[tp[i]]]++; for(int i = 1; i <= m; i++) tax[i] += tax[i - 1]; for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i]; } void suffix(){ for(int i = 1; i <= n; i++){ tp[i] = i; rank[i] = s[i]; } Rsort(); for(int w = 1, p; w < n; w <<= 1, m = p){ p = 0; for(int i = n - w + 1; i <= n; i++) tp[++p] = i; for(int i = 1; i <= n; i++) if(sa[i] > w) tp[++p] = sa[i] - w; Rsort(); swap(rank, tp); rank[sa[1]] = p = 1; for(int i = 2; i <= n; i++) rank[sa[i]] = cmp(tp, sa[i - 1], sa[i], w) ? p : ++p; if(p == n) return; } } int main(){ n = readint(); for(int i = 1; i <= n; i++) num[i] = s[i] = readint(); sort(num + 1, num + n + 1); m = unique(num + 1, num + n + 1) - (num + 1); for(int t, i = 1; i <= n; i++){ t = lower_bound(num + 1, num + m + 1, s[i]) - num; ref[t] = s[i]; s[i] = s[i + n] = t; } n <<= 1; suffix(); n >>= 1; int a; for(int i = 1; ; i++){ if(sa[i] <= n){ a = sa[i]; break; } } for(int i = 1; i < n; i++) printf("%d ", ref[s[a++]]); printf("%d", ref[s[a]]); return 0; }
或者SAM也可以做
但更吼的是最小表示法
#include <cstdio> const int maxn = 300000 + 10; int n, num[maxn]; int zx(){ int i = 1, j = 2, k = 0; int nxi, nxj, t; while(i <= n && j <= n && k <= n){ nxi = i + k; if(nxi > n) nxi -= n; nxj = j + k; if(nxj > n) nxj -= n; t = num[nxi] - num[nxj]; if(t == 0) k++; else{ if(t > 0) i += k + 1; else j += k + 1; if(i == j) i++; k = 0; } } return i < j ? i : j; } int main(){ scanf("%d", &n); for(int i = 1 ; i <= n; i++) scanf("%d", num + i); int a = zx(); for(int i = 1; i < n; i++){ printf("%d ", num[a++]); if(a > n) a -= n; } printf("%d", num[a]); return 0; }
以上是关于[BZOJ2882]工艺的主要内容,如果未能解决你的问题,请参考以下文章