ABC265のD問題 Iroha and Haikuを解説します。
問題を理解する
最初にこの問題を見た時に、ぱっと問題を理解できませんでした。
いくつか例を試してようやく理解できました。例示は理解の試金石です。
以下のような例を複数考えました。
問題のポイント
累積和という考え方です。
その名の通り、和を”積んで”いきます。
例えば、1 3 2 2というような数列の累積和を考えると、1 4 6 8となります。
(今回の問題では、最初は0となるようにしています。)
以下のような形で、累積和のvectorを作成しています。
入力例
10 5 7 5
1 3 2 2 2 3 1 4 3 2
回答例
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); ++i)
int main() {
int n;
ll p, q, r;
cin >> n >> p >> q >> r;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<ll> s(n+1); // vector a の累積和のvectorを準備。0スタートのため、サイズはn+1
s[0] = 0;
for (int i = 1; i <= n; i++) { // 累積和を作成
s[i] = s[i-1] +a[i-1];
}
set<ll> st;
rep(i, n+1) st.insert(s[i]); // 累積和で得られた値を全てstに入れる
// 累積和のある地点から見て、差がp、q、rとなっているものがstにあるかを調べている
// その「ある地点」というのをfor文で回して色々試している。
rep(i, n+1) {
ll start = s[i];
if (st.count(start + p) > 0 && st.count(start + p + q) > 0 && st.count(start + p + q + r) > 0) {
cout << "Yes" << endl; // 差がp、q、r全てを満たしている場合"Yes"を出力
return 0;
}
}
cout << "No" << endl; // 全てを試してなかったのであれば、"No"を出力
return 0;
}
コメント