「問題解」回文配列


タイトルの説明
 は、N個の整数の配列Aを与え、下付きは1からNである.各下付きiに対してA[i]=A[N-i+1]を満たす場合、配列は回文と呼ばれる. 例えば,配列A={1,2,3,2,1}が回文配列である. 配列Aが回文でない場合、隣接する2つの要素を結合する方法で回文配列を得ることができる.ただし、配列の要素数は、操作ごとに1減少します. 例えば,配列A={1,2,3}はエコー配列ではないが,A[1]とA[2]をマージすることで,{3,3}がエコー配列となる. 明らかに,どのような配列要素が与えられても,最大N−1回の操作を経て,1つの数にマージされると,配列Aは必ず回文配列である.だから、本題には必ず解がある.しかし、問題は、与えられた配列Aに対して、少なくとも何回の操作を経て、Aを返信配列にすることができるかということです.
入力フォーマット
1行目:1個の整数N、配列Aを表す要素の個数2行目:N個のスペースで区切られた整数、配列Aを表す
出力フォーマット
第1行:1個の整数、最小の操作回数を表す
サンプル
サンプル入力4
1 4 3 2

サンプル出力2
データ範囲とヒント
 1 4 3 2->5 3 2->5 5 30%のデータ 1≦N≦10 60%のデータ 1≦N≦1000 100%のデータ 1≦N≦106 1≦A[i]≦109
ぶんせき
私が初めてやったときは逆だったので、私たちが2つのポインタl,rを設定して、両側から2つの関数を比較して作るところだった.
int Pre(int index) {
	int sum = 0;
	for (int i = 1; i <= index; i ++) sum += a[i];
	return sum;
}
int Suf(int index) {
	int sum = 0;
	for (int i = index; i <= n; i ++) sum += a[i];
	return sum;
}

次の3つのケースがあります
  • Pre(l)>Suf(r)の場合、r--
  • Pre(l)の場合
  • Pre(l)=Suf(r)の場合、l+,r--
  • もちろん,接頭辞と接尾辞の和を用いずに,元の配列で直接加算すればよい(場合3は加算せずに直接スキップできる)
    コード#コード#
    #include 
    #include 
    using namespace std;
    
    const int M = 1e6 + 5;
    int a[M];
    int ans, n;
    
    int main() {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i ++) {
    		scanf("%d", &a[i]);
    	}
    	for (int l = 1, r = n; l < r; ) {
    		if (a[l] < a[r]) {
    			a[++ l] += a[l - 1];
    			++ ans;
    		}
    		if (a[l] > a[r]) {
    			a[-- r] += a[r + 1];
    			++ ans;
    		}
    		if (a[l] == a[r]) {
    			a[++ l] += a[l - 1];
    			a[-- r] += a[r + 1];
    			//l ++, r --;
    		}
    	}
    	printf("%d", ans);
    	return 0;
    }