読者です 読者をやめる 読者になる 読者になる

Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

IOI 2005-day1 Mean Sequence

問題文 : 平均数列

解法 :
数列の初項を決めると, 残りの数列の値も一意に定まる.
更に, 初項k の平均数列が作れなければ, 初項をk + 1 とする平均数列(またはk - 1 とする平均数列, あるいは両方) が作れないことが分かる. ゆえに, この数列の初項の値は連続していることが分かる.
そこで, 初項の値としてありうる範囲を計算すると, 2 * m1 - m2 ≦ x ≦ m1 となることが分かる. この値を遷移させて行き, 最終項としてありうる数の上限と下限を定める.
値の遷移はO(1) で行えるため, 計算量はO(n) となる.

コード :

#include <cstdio>
#include <climits>
#include <algorithm>

using namespace std;
typedef long long int lint;

lint t;

int main()
{
	int n;
	
	scanf("%d", &n);
	
	lint upper, lower;
	lint nextu = LLONG_MAX, nextl = LLONG_MIN;
	lint prev = -1;
	for (int i = 0; i < n; i++){
		scanf("%lld", &t);
		if (~prev){
			upper = min(nextu, max(prev, 2 * prev - t));
			lower = max(nextl, min(prev, 2 * prev - t));
			nextu = 2 * prev - lower;
			nextl = 2 * prev - upper;
			//printf("upper = %lld lower = %lld nextu = %lld nextl = %lld\n", upper, lower, nextu, nextl);
		}
		prev = t;
	}
	//printf("upper = %lld, lower = %lld\n", upper, lower);
	printf("%lld\n", max(0ll, upper - lower + 1));
	
	return (0);
}