Lilliput Steps

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

KOJ 0021 - MAX Sequence

問題 : MAX Sequence


解法 :

少し場合分けをすれば, 各クエリに対して$O(1)$ で答えが求まる.
数列は, 基本的には一定の値に収束するかずっと1 ずつ増加する.
厄介な場合として, 入力された範囲で配列が再帰的に自分を参照する場合がある. これを回避するには数列を適当な長さまで伸ばして, 最初の何項かを事前計算すれば良い. (前計算する範囲の上界を, 問題の性質から抑えられた気がしたが忘れてしまった……)

コード :

#include <cstdio>
#include <algorithm>

using namespace std;

int main()
{
	int m, q;
	
	while (scanf("%d %d", &m, &q) && m){
		long long int a[1024], maxi = -1;
		
		for (int i = 1; i <= m; i++){
			scanf("%lld", a + i);
			maxi = max(maxi, a[i]);
		}
		
		for (int i = m + 1; i <= 1023; i++){
			a[i] = a[min((long long int)(i - 1), maxi)] + 1;
			maxi = max(a[i], maxi);
		}
		
		for (int i = 0; i < q; i++){
			long long int x;
			scanf("%lld", &x);
			
			if (x <= 1023) printf("%lld", a[x]);
			else if (maxi <= 1023){
				if (a[maxi] + 1 <= 1023) printf("%lld", a[maxi] + 1);
				else printf("%lld", a[maxi] + x - 1023);
			}
			else {
				if (a[1023] + x - 1023 <= maxi || a[1023] >= 1023) printf("%lld", a[m] + x - m);
				else printf("%lld", maxi);
			}
			
			printf("%c", i == q - 1 ? '\n' : ' ');
		}
	}
	
	return (0);
}