此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。
题目链接:http://poj.org/problem?id=3617
洛谷题目链接:https://www.luogu.org/problem/show?pid=2870
题目大意:
给定一个长度为N(1<=N<=30000)的字母序列,每次可以从序列头部或尾部取出一个字母加入一个队列的尾部,求此队列字典序最小的排列。
每输出80个字母,换行一次。
分析:
每次比较序列首部和尾部,取出较小的一个,如果相等就继续往下比较,直到大小出现差异或者比较变量相遇。
POJ的AC代码(洛谷数据太强,改了半天不是TLE就是WA,求大神找错):
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 char def[50005],line[50005]; 6 int head,tail,n,tot = 0; 7 inline void op(int x) 8 { 9 if(x == 0) 10 { 11 while(head <= tail) 12 line[++ tot] = def[head ++],line[++ tot] = def[tail --]; 13 return; 14 } 15 else if(x == 1) 16 { 17 if(def[head] == def[tail]) 18 line[++ tot] = def[head ++]; 19 else if(def[head] < def[tail]) 20 { 21 line[++ tot] = def[head ++]; 22 return; 23 } 24 else if(def[tail] < def[head]) 25 { 26 line[++ tot] = def[tail --]; 27 return; 28 } 29 } 30 else if(x == 2) 31 { 32 if(def[head] == def[tail]) 33 line[++ tot] = def[tail --]; 34 else if(def[head] < def[tail]) 35 { 36 line[++ tot] = def[head ++]; 37 return; 38 } 39 else if(def[tail] < def[head]) 40 { 41 line[++ tot] = def[tail --]; 42 return; 43 } 44 } 45 46 } 47 48 void solve(int l,int r) 49 { 50 for(int i = 1;;++ i) 51 { 52 if(l >= r) 53 { 54 op(0); 55 break; 56 } 57 if(def[l] == def[r]) 58 { 59 l++,r--; 60 continue; 61 } 62 if(def[l] < def[r]) 63 { 64 op(1); 65 break; 66 } 67 if(def[r] < def[l]) 68 { 69 op(2); 70 break; 71 } 72 } 73 } 74 75 int main() 76 { 77 char x; 78 scanf("%d",&n); 79 x = getchar(); 80 for(int i = 1;i <= n;++ i) 81 { 82 while(x < ‘A‘) x = getchar(); 83 def[i] = x,x = getchar(); 84 } 85 head = 1,tail = n; 86 while(head <= tail && tot <= n) 87 { 88 if(def[head] < def[tail]) 89 line[++ tot] = def[head ++]; 90 else if(def[tail] < def[head]) 91 line[++ tot] = def[tail --]; 92 else 93 solve(head,tail); 94 } 95 for(int i = 1;i <= n;++ i) 96 { 97 putchar(line[i]); 98 if(i%80 == 0) 99 putchar(‘\n‘); 100 } 101 return 0; 102 }
时间: 2024-09-29 09:36:17