POJ3617 题解

358 阅读1分钟

题目链接

思路

求字典序最小就把小的字母尽量放到前面。因此只需要从首尾取更小的那个加入到新串。如果首尾字符相同,就需要再比较第二个和倒数第二个,若仍相同就比较第三个和倒数第三个,以此类推。哪一侧的更小就先选哪一侧。
假如当前字符串为C...C,第二个和倒数第二个字符分别为l,r(l<r)。由上述可知应当先选左边的C。若l>=C,那么下一步直接选最后一个C,与之前先选右边的C没有差别。若l<=C,下一步选l。必定比先选后边的C更优。

其他

认真读题。这道题要求80个字符为一行,刚开始没看见导致PE,后来加上计数器又忘记清零。

代码

#include<iostream>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
using namespace std;
const int N=3E4+10;
int n,cnt;
int a[N];
int main()
{
	cin>>n;
	char inp;
	rep(i,1,n)
	{
		cin>>inp;
		a[i]=inp-'A';
	}
	int l=1,r=n;
	while(l<=r)
	{
		char ans='A';
		if(a[l]<a[r])
		{
			ans+=a[l];
			++l;
		}
		else if(a[l]>a[r])
		{
			ans+=a[r];
			--r;
		}
		else
		{
			int tl=l+1,tr=r-1;
			while(tl<tr && a[tl]==a[tr])
			{
				++tl;--tr;
			}
			if(tl==tr)
			{
				ans+=a[l];
				++l;
			}
			else if(a[tl]<a[tr])
			{
				ans+=a[l];
				++l;
			}
			else
			{
				ans+=a[r];
				--r;
			}
		}
		cout<<ans;
		++cnt;
		if(cnt==80)
		{
			cnt=0;
			cout<<endl;
		}
	}
}