結果
問題 | No.284 門松と魔法(2) |
ユーザー | Yang33 |
提出日時 | 2018-09-27 22:20:44 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 354 ms / 5,000 ms |
コード長 | 4,956 bytes |
コンパイル時間 | 2,207 ms |
コンパイル使用メモリ | 178,552 KB |
実行使用メモリ | 16,256 KB |
最終ジャッジ日時 | 2024-10-12 04:36:49 |
合計ジャッジ時間 | 5,707 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 2 ms
5,248 KB |
testcase_07 | AC | 2 ms
5,248 KB |
testcase_08 | AC | 2 ms
5,248 KB |
testcase_09 | AC | 2 ms
5,248 KB |
testcase_10 | AC | 2 ms
5,248 KB |
testcase_11 | AC | 2 ms
5,248 KB |
testcase_12 | AC | 2 ms
5,248 KB |
testcase_13 | AC | 2 ms
5,248 KB |
testcase_14 | AC | 2 ms
5,248 KB |
testcase_15 | AC | 2 ms
5,248 KB |
testcase_16 | AC | 3 ms
5,248 KB |
testcase_17 | AC | 2 ms
5,248 KB |
testcase_18 | AC | 2 ms
5,248 KB |
testcase_19 | AC | 2 ms
5,248 KB |
testcase_20 | AC | 2 ms
5,248 KB |
testcase_21 | AC | 2 ms
5,248 KB |
testcase_22 | AC | 2 ms
5,248 KB |
testcase_23 | AC | 17 ms
5,248 KB |
testcase_24 | AC | 228 ms
16,000 KB |
testcase_25 | AC | 85 ms
9,600 KB |
testcase_26 | AC | 2 ms
5,248 KB |
testcase_27 | AC | 2 ms
5,248 KB |
testcase_28 | AC | 2 ms
5,248 KB |
testcase_29 | AC | 329 ms
16,256 KB |
testcase_30 | AC | 251 ms
16,256 KB |
testcase_31 | AC | 155 ms
16,256 KB |
testcase_32 | AC | 354 ms
16,128 KB |
testcase_33 | AC | 150 ms
16,128 KB |
testcase_34 | AC | 155 ms
16,128 KB |
testcase_35 | AC | 2 ms
5,248 KB |
testcase_36 | AC | 2 ms
5,248 KB |
testcase_37 | AC | 166 ms
16,256 KB |
testcase_38 | AC | 127 ms
16,128 KB |
testcase_39 | AC | 3 ms
5,248 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using VS = vector<string>; using LL = long long; using VI = vector<int>; using VVI = vector<VI>; using PII = pair<int, int>; using PLL = pair<LL, LL>; using VL = vector<LL>; using VVL = vector<VL>; #define ALL(a) begin((a)),end((a)) #define RALL(a) (a).rbegin(), (a).rend() #define SZ(a) int((a).size()) #define SORT(c) sort(ALL((c))) #define RSORT(c) sort(RALL((c))) #define UNIQ(c) (c).erase(unique(ALL((c))), end((c))) #define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++) #define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--) #define debug(x) cerr << #x << ": " << x << endl const int INF = 1e9; const LL LINF = 1e16; const LL MOD = 1000000007; const double PI = acos(-1.0); int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 }; int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 }; /* ----- 2018/09/26 Problem: yukicoder 284 / Link: http://yukicoder.me/problems/no/284 ----- */ /* ------問題------ かつて、kamipeipaa君の家の庭には3本しか竹はありませんでした。 今や1列に並んだN本の竹からなる竹林があります。i番目の竹の高さはAiです。 kamipeipaa君は ・竹の本数がM(3≤M)本、i番目の竹の高さがBiであるときに、1<i<MについてBi−1,Bi,Bi+1が全て異なり、3つの要素の中でBiが最大または最小 ・竹が1本も存在しない。 のどちらかの条件を満たすようにしたいと考えています。 kamipeipaa君は"ある竹を1本選んで消滅させる"魔法を繰り返し使うことで、この条件を満たすようにしたいと考えています。 この条件を満たすように0本以上の竹を消滅させたとき、最大で何本の竹を残すことが可能かkamipeipaa君に教えてあげてください。 -----問題ここまで----- */ /* -----解説等----- https://speakerdeck.com/camypaper/yukicoder-no-284 ----解説ここまで---- */ struct Data { int length, last, lastprv; Data(int a = 0, int b = -1, int c = -1) :length(a), last(b), lastprv(c) {} bool operator < (const Data & x)const { return length < x.length; } bool operator > (const Data & x)const { return length > x.length; } }; struct Node { Data d[2]; Node() {} Data fetch(int sec) { return d[0].lastprv != sec ? d[0] : d[1]; } }; struct SegTreeG { inline Node merge(Node &a, Node &b) { // dataのmerge Node ret; if (a.d[0] > b.d[0]) { ret.d[0] = a.d[0]; if (a.d[1] > b.d[0]) { ret.d[1] = a.d[1]; } else if (ret.d[0].lastprv != b.d[0].lastprv) { ret.d[1] = b.d[0]; } else { ret.d[1] = max(a.d[1], b.d[1]); } } else { ret.d[0] = b.d[0]; if (b.d[1] > a.d[0]) { ret.d[1] = b.d[1]; } else if (ret.d[0].lastprv != a.d[0].lastprv) { ret.d[1] = a.d[0]; } else { ret.d[1] = max(a.d[1], b.d[1]); } } return ret; } int N; vector<Node> dat; SegTreeG(int _N) { N = 1; while (N < _N)N *= 2; dat = vector<Node>(N * 2 - 1); } void update(int k, Node &val) { k += N - 1; dat[k] = val; // ! while (k) { k = (k - 1) / 2; dat[k] = merge(dat[k * 2 + 1], dat[k * 2 + 2]); } } Node query(int a, int b, int k, int l, int r) { if (r <= a || b <= l)return Node(); if (a <= l && b >= r)return dat[k]; Node v1 = query(a, b, k * 2 + 1, l, (l + r) / 2); Node v2 = query(a, b, k * 2 + 2, (l + r) / 2, r); return merge(v1, v2); } inline Node query(int a, int b) { return query(a, b, 0, 0, N); } }; int main() { cin.tie(0); ios_base::sync_with_stdio(false); LL N; cin >> N; VI a(N); FOR(i, 0, N) { cin >> a[i]; } VI b = a; SORT(b); UNIQ(b); FOR(i, 0, N) { a[i] = lower_bound(ALL(b), a[i]) - b.begin(); } SegTreeG up(SZ(a)); SegTreeG dw(SZ(a)); FOR(i, 0, SZ(a)) { Data dwMax = dw.query(0, a[i]).fetch(a[i]); Data upMax = up.query(a[i] + 1, SZ(a)).fetch(a[i]); if (dwMax.length > 0) { Data dwSecondL = dw.query(0, dwMax.last).fetch(a[i]); Data dwSecondR = dw.query(dwMax.last + 1, a[i]).fetch(a[i]); Data dwSecondTop = max(dwSecondL, dwSecondR); Node n; n.d[0] = Data(dwMax.length + 1, a[i], dwMax.last); n.d[1] = Data(dwSecondTop.length + 1, a[i], dwSecondTop.last); up.update(a[i], n); } else { Node n; n.d[0] = Data(1, a[i], -1); n.d[1] = Data(); up.update(a[i], n); } if (upMax.length > 0) { Data upSecondL = up.query(a[i] + 1, upMax.last).fetch(a[i]); Data upSecondR = up.query(upMax.last + 1, SZ(a)).fetch(a[i]); Data upSecondTop = max(upSecondL, upSecondR); Node n; n.d[0] = Data(upMax.length + 1, a[i], upMax.last); n.d[1] = Data(upSecondTop.length + 1, a[i], upSecondTop.last); dw.update(a[i], n); } else { Node n; n.d[0] = Data(1, a[i], -1); n.d[1] = Data(); dw.update(a[i], n); } } int ans = max(up.query(0, SZ(a)).d[0].length, dw.query(0, SZ(a)).d[0].length); if (ans <= 2)ans = 0; cout << ans << "\n"; return 0; }