ARC082 D : Derangement(400)

作成日:2017.09.03
最終更新日:2017.09.03

問題概要

問題本文

 $1,2,...,N$の順列$p_1,p_2,...p_N$が与えられる。 操作「順列で隣り合う二つの数を選んで入れ替える」を$0$回以上行うことで、すべての$i$において$p_i \neq i$となるようにする。 必要な操作の最小回数を求めよ。
制約
$2 \leq N \leq 10^5$
数列$\{p_i\}$は$1,2,...,N$の順列

考え方

 $p_i = i$である時は$p_{i-1}$あるいは$p_{i+1}$と入れ替えなければならない。 この時$p_{i-1} \neq i , p_{i+1} \neq i$であることから、$p_i$に対しては1回だけ操作を行えば良い。 また、それによって新たに操作を行わなければならない要素は生じない。 よって$p_i = i$となる$i$の個数だけ操作を行えば良い。 但し$p_i = i$かつ$p_{i+1} = i+1$の時はこの2つの要素を選んで操作を行うことで操作の回数を1回減らすことができる。 以上より、先頭から要素を見ていき$p_i = i$となるものが現れたら$p_{i+1}$と操作を行うことを繰り返せば良いことが分かる。

ソースコード

マクロ等はこちら

const int MC = 100010;
int N;
int p[MC];

int main(){
	scanf("%d" , &N);
	repp(i,1,N+1){
		scanf("%d" , p + i);
	}
	int ans = 0;
	repp(i,1,N+1){
		if(p[i] == i){
			++ans;
			++i;
		}
	}
	printf("%d\n" , ans);
	return 0;
}

解法まとめ

 先頭から要素を見ていき$p_i = i$となるものが現れたら$p_{i+1}$と操作を行う。(10-17行)

ARC082の他の問題 C E F

自己紹介

プログラミングとか合成音声とか
詳しくはこちら
twitter

プライバシーポリシー

個人情報利用についてはこちら

最終更新日:2023.03.05

お問い合わせ

このページに関するお問い合わせはこちら

競技プログラミングMENU

問題を解くまでの道のり

その他

全体MENU

寄付モドキ

0冂から10000冂まで
詳しくはこちら