POJ 3581-Sequence(字尾陣列)
Sequence
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 6485 | Accepted: 1429 | |
Case Time Limit: 2000MS |
Description
Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.
The alphabet order is defined as follows: for two sequence {A1, A2, ..., An} and {B1, B2, ..., Bn}, we say {A1, A2, ..., An} is smaller than {B1, B2, ..., Bn} if and only if there exists such i ( 1 ≤ i ≤ n) so that we have Ai < Bi and Aj = Bj for each j < i.
Input
The first line contains n. (n ≤ 200000)
The following n lines contain the sequence.
Output
output n lines which is the smallest possible sequence obtained.
Sample Input
5 10 1 2 3 4
Sample Output
1 10 2 4 3
Hint
{10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}
Source
POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu
題目意思:
有一個陣列,分割成三份,每份翻轉後,得到的最小的字典序?
解題思路:
字尾陣列。先確定第一段,因為A1是最大的,所以求反轉之後字串中字典序最小的字尾。
再將剩餘部分分成兩段,計算兩個原序列並將得到的新序列反轉後的字尾陣列,從中選取字典序最小的合適的字尾。
cin超時,輸入輸出外掛WA,scanf才AC…坎坷…
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
#define maxn 200100
int n,k,a[maxn];
int rev[maxn],sa[maxn];
int rank[maxn*2],tmp[maxn*2];
bool compare_sa(int i,int j)//倍增法,比較rank
{
if(rank[i]!=rank[j]) return rank[i]<rank[j];
else
{
int ri=i+k<=n?rank[i+k] :-1;
int rj=j+k<=n?rank[j+k] :-1;
return ri<rj;
}
}
void construct_sa(int s[],int N,int sa[])//計算s的字尾陣列
{
for(int i=0; i<=N; ++i)//初始長度為1,rank為字元編碼
{
sa[i]=i;
rank[i]=i<N?s[i] :-1;
}
for(k=1; k<=N; k*=2)//倍增法求字尾陣列
{
sort(sa,sa+N+1,compare_sa);
tmp[sa[0]]=0;
for(int i=1; i<=N; ++i)
tmp[sa[i]]=tmp[sa[i-1]]+(compare_sa(sa[i-1],sa[i])?1:0);
for(int i=0; i<=N; ++i)
rank[i]=tmp[i];
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0; i<n; ++i)
cin>>a[i];
//solve();
reverse_copy(a,a+n,rev);//a不變,反轉a之後存入rev陣列
construct_sa(rev,n,sa);//求字尾陣列
int p1;
for(int i=0; i<n; ++i)//確定第一段的分割位置
{
p1=n-sa[i];
if((p1>=1)&&n-p1>=2) break;
}
//cout<<"p1="<<p1<<endl;
int m=n-p1;
reverse_copy(a+p1,a+n,rev);
reverse_copy(a+p1,a+n,rev+m);
construct_sa(rev,m*2,sa);
int p2;
for(int i=0; i<=2*m; ++i)//確定第二段的分割位置
{
p2=p1+m-sa[i];
if((p2-p1>=1)&&n-p2>=1) break;
}
//cout<<"p2="<<p2<<endl;
reverse(a,a+p1);
reverse(a+p1,a+p2);
reverse(a+p2,a+n);
for(int i=0; i<n; ++i)
cout<<a[i]<<endl;
return 0;
}
/**
5
10
1
2
3
4
**/
相關文章
- POJ 1743 Musical Theme(字尾陣列)陣列
- POJ1743 Musical Theme(字尾陣列 二分)陣列
- POJ2774Long Long Message(字尾陣列模板)陣列
- 字尾陣列模板陣列
- 字尾陣列 SA陣列
- 字尾陣列,SA陣列
- POJ 2217-Secretary(字尾陣列+高度陣列-最大公共子串長度)陣列
- 字尾陣列複習陣列
- 字尾陣列(後續)陣列
- 字尾陣列詳解陣列
- 【筆記】字尾陣列筆記陣列
- POJ 3415 Common Substrings(字尾陣列求重複字串)陣列字串
- [POJ 3415] Common Substrings (字尾陣列+單調棧優化)陣列優化
- poj 2774 求兩字串的最長公共子串 字尾陣列字串陣列
- OI loves Algorithm——字尾陣列Go陣列
- POJ 2774-Long Long Message(字尾陣列+高度陣列-最大公共子串長度)陣列
- POJ 3693 Maximum repetition substring(字尾陣列求最長重複子串)陣列
- POJ 3294 Life Forms(字尾陣列求k個串的最長子串)ORM陣列
- 學習筆記----字尾陣列筆記陣列
- 字尾陣列 學習筆記陣列筆記
- 字尾陣列學習筆記陣列筆記
- POJ 1743 Musical Theme (字尾陣列,求最長不重疊重複子串)陣列
- POJ 2752+KMP+利用next陣列性質求出所有相同的字首和字尾KMP陣列
- BZOJ2882: 工藝(字尾陣列)陣列
- POJ 3415-Common Substrings(字尾陣列+單調棧-公共子串的長度)陣列
- poj 2481 樹狀陣列陣列
- P10469 字尾陣列(Hash+二分)陣列
- 【資料結構與演算法】字串匹配(字尾陣列)資料結構演算法字串匹配陣列
- Codeforces #123D: 字尾陣列+單調棧3D陣列
- SPOJ 694 求一個字串有多少子串 字尾陣列字串陣列
- ural 1297 最長迴文子串 字尾陣列陣列
- 洛谷P5108 仰望半月的夜空(字尾陣列)陣列
- SPOJ 687. Repeats(字尾陣列求最長重複子串)陣列
- URAL 1297. Palindrome(字尾陣列求最大回文串)陣列
- HDU5147 Sequence II(樹狀陣列+字首和+字尾和)陣列
- BZOJ 4650 [Noi2016]優秀的拆分:字尾陣列陣列
- SPOJ 694. Distinct Substrings,705. New Distinct Substrings(字尾陣列)陣列
- POJ 3928 Ping pong(樹狀陣列)陣列