PKU 3581 Sequence 解题报告

来源:互联网 发布:ubuntu windows10 编辑:程序博客网 时间:2024/05/18 02:59
  1. /*
  2.   Title: Sequence
  3.   Author: Jeff
  4.   Time:  2008/10/29
  5.   Complexity: O(N*log(N));
  6.   Result: 7364K 1829MS/ AC
  7.   Reference: 
  8.         Discuss
  9.   Description: 
  10.         给定一个数组{A1, A2, …, An} 满足A1 > A2, …, An,
  11.         把该数组分成三段,单独翻转,使得数组的字典序最小。
  12.   Tips:
  13.         后缀数组。 
  14.         输入数据时候反序输入,再求后继数组。
  15.         比如原始数据:
  16.         6
  17.         10 1 1 2 3 4
  18.         反序输入就是
  19.         4 3 2 1 1 10
  20.         第一部分就是满足能将该序列分成三段的排在最前的后缀数。就是 1 1 10 了。
  21.         去掉这一部分之后再求一次后缀数组,
  22.         第二部分就是满足能将该序列分成两段的最大的后缀数。就是 2
  23.         再输出最后一部分 4 3
  24.         结果 1 1 10 2 4 3
  25.         
  26.         为什么要求两次后缀数组呢,看下面一组数据
  27.         7
  28.         5 0 2 1 2 1 3 
  29.         (反序) 3 1 2 1 2 0 5
  30.         按照第一次求后缀数组的结果:
  31.         一:0 5
  32.         二:1 2 (因为后缀1 2 0 5比1 2 1 2 0 5要小) 
  33.         三:3 1 2 
  34.         最后结果:0 5 1 2 3 1 2 (WA) 
  35.         所以要去掉第一段结果再求一次后缀数组:
  36.         (二三段反序) 3 1 2 1 2
  37.         现在后缀1 2 1 2 比 1 2要小,所以得到正确结果: 
  38.         二:1 2 1 2
  39.         三:3
  40.         最后结果:0 5 1 2 1 2 3 
  41.         
  42.   p.s. 
  43.         只求一次后缀数组,结果WA掉了。。。 
  44. */
  45. #include <cstdio>
  46. #include <cstring>
  47. #include <algorithm>
  48. using namespace std;
  49. const int MAX = 200001;
  50. struct Sfx{
  51.     int idx;
  52.     int key[2];
  53.     bool operator<(const Sfx &other)const{
  54.         return key[0] < other.key[0] || 
  55.             key[0] == other.key[0] && key[1] < other.key[1];    
  56.     }    
  57. };
  58. Sfx g_sfx[2][MAX], *sa = g_sfx[0], *temp_sa = g_sfx[1];
  59. int cnt[MAX];
  60. int rank[MAX];
  61. int A[MAX];
  62. int n;
  63. void cSort(Sfx *in, int key, Sfx *out){
  64.     memset(cnt, 0, sizeof(cnt));;
  65.     for(int i = 0; i < n; i++)
  66.         cnt[in[i].key[key]]++;
  67.     for(int i = 1; i < n; i++)
  68.         cnt[i] += cnt[i-1];
  69.     for(int i = n - 1; i >= 0; i--)
  70.         out[ --cnt[in[i].key[key]] ] = in[i];
  71. }
  72. void build_sfx(){
  73.     for(int i = n-1; i >= 0; i--){
  74.             sa[i].idx = sa[i].key[1] = i;
  75.             sa[i].key[0] = A[i];
  76.         }    
  77.         sort(sa, sa+n);
  78.         for(int i = 0; i < n; i++)sa[i].key[1] = 0;
  79.         
  80.         int wid = 1;
  81.         
  82.         while(wid < n){
  83.             rank[sa[0].idx] = 0;
  84.             for(int i = 1; i < n; i++){
  85.                 rank[sa[i].idx] = rank[sa[i-1].idx];
  86.                 if(sa[i-1] < sa[i])rank[sa[i].idx]++;
  87.             }
  88.             for(int i = 0; i < n; i++){
  89.                 sa[i].idx = i;
  90.                 sa[i].key[0] = rank[i];
  91.                 sa[i].key[1] = i + wid < n ? rank[i + wid] : 0;    
  92.             }
  93.             cSort(sa, 1, temp_sa); cSort(temp_sa, 0, sa);
  94.             wid *= 2;    
  95.         }
  96.         //printf("/n");for(int i = 0; i < n; i++)printf("%d ", A[i]);printf("/n");
  97.         //printf("sa: ");for(int i = 0; i < n; i++)printf("%d ", sa[i].idx);printf("/n");
  98.         //printf("r: ");for(int i = 0; i < n; i++)printf("%d ", rank[i]); printf("/n");
  99. }
  100. int main(){
  101.     freopen("in.txt""r", stdin);
  102.     freopen("out.txt""w", stdout);
  103.     while(scanf("%d", &n) != EOF){
  104.         for(int i = n-1; i >= 0; i--)
  105.             scanf("%d", &A[i]);
  106.         build_sfx();
  107.         int ans[4];
  108.         ans[0] = n;
  109.         for(int i = 0, j = 1; j <= 1; i++){
  110.             if(sa[i].idx < ans[j-1])
  111.                 if(sa[i].idx >= 3 - j){
  112.                     ans[j] = sa[i].idx;
  113.                     for(int k = ans[j]; k < ans[j-1]; k++)
  114.                         printf("%d/n", A[k]);
  115.                     j++;    
  116.                 }
  117.         }
  118.         n = ans[1];
  119.         build_sfx();
  120.         for(int i = 0, j = 2; j <= 2; i++){
  121.             if(sa[i].idx < ans[j-1])
  122.                 if(sa[i].idx >= 3 - j){
  123.                     ans[j] = sa[i].idx;
  124.                     for(int k = ans[j]; k < ans[j-1]; k++)
  125.                         printf("%d/n", A[k]);
  126.                     j++;    
  127.                 }
  128.         }
  129.         for(int k = 0; k < ans[2]; k++)printf("%d/n", A[k]);
  130.         break;
  131.         //printf("/n");
  132.     } 
  133.     return 0;    
  134. }