結果
| 問題 | No.209 Longest Mountain Subsequence |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-03-03 21:12:10 |
| 言語 | D (dmd 2.112.0) |
| 結果 |
AC
|
| 実行時間 | 93 ms / 2,000 ms |
| コード長 | 1,767 bytes |
| 記録 | |
| コンパイル時間 | 2,512 ms |
| コンパイル使用メモリ | 172,568 KB |
| 実行使用メモリ | 7,720 KB |
| 最終ジャッジ日時 | 2026-03-03 21:12:14 |
| 合計ジャッジ時間 | 3,484 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 6 |
ソースコード
module main;
// https://kmjp.hatenablog.jp/entry/2015/05/15/1100 より
// 動的計画法
import std;
// 多次元配列をある値で埋める
void fill(A, T)(ref A a, T value) if (isArray!A)
{
alias E = ElementType!A;
static if (isArray!E) {
foreach (ref e; a)
fill(e, value);
} else {
a[] = value;
}
}
// https://forum.dlang.org/post/k1js2b$1bef$1@digitalmars.com より
// 変数の参照
struct Ref(T) {
private T* _payload;
this(ref T i) { _payload = &i; }
@property ref T deref() { return *_payload; }
alias deref this;
}
auto ref_(T)(ref T arg) { return Ref!T(arg); }
// B[1 .. j]が狭義単調増加、B[j .. K]が狭義単調減少
// 1 <= j <= N にわたって左右の裾野の長さを調べる
int N;
int[] A;
int[][] L, R;
int left(int l, int r)
{
auto ret = ref_(L[l][r]);
if (ret < 0) {
ret = 0;
foreach (x; 0 .. l)
if (A[x] < A[l] && A[l] - A[x] < A[r] - A[l])
ret = max(ret, left(x, l) + 1);
}
return ret;
}
int right(int l, int r)
{
auto ret = ref_(R[l][r]);
if (ret < 0) {
ret = 0;
foreach (x; r + 1 .. N)
if (A[x] < A[r] && A[r] - A[x] < A[l] - A[r])
ret = max(ret, right(r, x) + 1);
}
return ret;
}
void main()
{
foreach (_; 0 .. readln.chomp.to!int) {
// 入力
N = readln.chomp.to!int;
A = readln.split.to!(int[]);
// 答えの計算
L = uninitializedArray!(int[][])(N, N);
fill(L, -1);
R = uninitializedArray!(int[][])(N, N);
fill(R, -1);
int ma = -1;
foreach (i; 0 .. N) {
int lm = 0, rm = 0;
// 左側
foreach (x; 0 .. i)
if (A[x] < A[i])
lm = max(lm, left(x, i) + 1);
// 右側
foreach (x; i + 1 .. N) {
if (A[x] < A[i])
rm = max(rm, right(i, x) + 1);
}
ma = max(ma, lm + rm + 1);
}
// 答えの出力
writeln(ma);
}
}