[BZOJ3395]迴文串

問題描述
有n(1≤n≤4)種字母,第種字母有ai(1≤ai≤10^9)個,你可以任意排列這些字母的順序來組成一個字符串。你的任務是判斷是否存在一種排列方式使得字符串中本質不同的迴文子串的個數爲n。

輸入格式
每個輸入文件包含多組數據。
輸入文件的第一行只有一個正整數T(1≤T≤10),表示數據的組數。
接下來依次輸入T組數據。
每組數據的第一行,包含一個正整數n。
每組數據的第二行,包含n個正整數a1,a2, ··· ,an。

輸出格式
對於每組輸入數據依次輸出一行答案,若存在輸出YES,若不存在輸出NO。

樣例輸入
1
4
2 2 5 5

樣例輸出
YES

樣例解釋
令s(l,r)表示字符串中下標從l到r的連續的一段,若∃l,r ,s ,s(l,r) = t,則稱t是s的子串。
rev(s)表示字符串s的倒序,若s = rev(s),則稱s是迴文串。
若s ≠ t,則稱s,t本質不同。
記這四種字母分別爲a,b,c,d,字符串cdacdbcdacdbcd 的本質不同的迴文子串共4個,分別是a,b,c,d,所以存在。


來源 by Quack


題解:
由題意可推得,當字符串中只有長度爲1的迴文子串(即單個字母)時,條件才成立。

知道這個條件,題就很好做了,直接分類討論。

當n=1時,只有1種字母,其數量只能爲1;

當n=2時,有2種字母,其數量只能各爲1;

當n=3時,有3種字母,最多數量的字母和最少的之差不能超過1;

當n=4時,有4種字母。因爲2個相同字母中間至少有2個不同的字母將其隔開(如abca),所以按數量排序,每次選大的三個,同時減去其中最小數的值,反覆操作(其實也就2次)直到不爲0的數≤2個,看其值是否≤1。


#include<cstdio>
#include<algorithm>
using namespace std;
int T, n, A[5];

int main() {
	for( scanf( "%d", &T ); T; T-- ) {
		scanf( "%d", &n ); for( int i=0; i<n; i++ ) scanf( "%d", &A[i] );
		if( n==1 ) A[0]==1 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==2 ) A[0]+A[1]==2 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==3 ) sort( A, A+n ), A[2]-A[0]<=1 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==4 ) {
			for( int i=0; i++<2; ) sort( A, A+n ), A[3]-=A[1], A[2]-=A[1], A[1]=0;
			A[2]<=1 && A[3]<=1 ? printf( "YES\n" ) : printf( "NO\n" );
		}
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章