UNIQUE VISION Programming Contest 2024 Spring(AtCoder Beginner Contest 346) - AtCoder
B - Piano
w, b の制約が 100 以下のため十分な長さの s を用意しておいて全探索する
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' const string t = "wbwbwwbwbwbw"; int main() { int w,b; cin >> w >> b; string s; REP(i,100) s += t; REP(i,12) { int cw = 0, cb = 0; int j = i; while(1) { if (cw == w && cb == b) { cout << "Yes" << endl; return 0; } if (cw > w || cb > b) break; if (s[j] == 'w') cw++; if (s[j] == 'b') cb++; j++; } } cout << "No" << endl; return 0; }
C - Σ
1 〜 k までの等差数列の和を最初に求めておいて、a の数列から k 以下の値のうち、重複を取り除いたものを引く
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; int main() { int n,k; cin >> n >> k; vector<int> a(n); REP(i,n) cin >> a[i]; ll ans = (ll)(1+k)*k/2; unordered_set<int> st; REP(i,n) if (a[i] <= k) st.insert(a[i]); for(auto v: st) ans -= v; cout << ans << endl; return 0; }
D - Gomamayo Sequence
以下のような 3次元の DP で遷移
dp[i][j][k] - i: 何文字目までみたか - j: 良い文字列フラグ - k: 最後の文字 0 or 1
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; const ll LINF = numeric_limits<ll>::max(); template<class T> void chmin(T& a, T b) { a = min(a,b); } int main() { int n; cin >> n; string s; cin >> s; vector<int> c(n); REP(i,n) cin >> c[i]; vector<int> si(n); REP(i,n) si[i] = s[i]-'0'; // dp[i][j][k] // i: 何文字目までみたか // j: 良い文字列フラグ // k: 最後の文字 0 or 1 vector dp(n+1,vector(2,vector<ll>(2,LINF))); dp[1][0][si[0]] = 0; dp[1][0][si[0]^1] = c[0]; auto f = [&](int i, int j, int k, int now, int cost) { if (now == k && j == 0) chmin(dp[i+1][1][now], dp[i][j][k] + cost); if (now != k) chmin(dp[i+1][j][now], dp[i][j][k] + cost); }; for(int i = 1; i < n; i++) REP(j,2) REP(k,2) { if (dp[i][j][k] == LINF) continue; f(i,j,k,si[i],0); // 操作しない f(i,j,k,si[i]^1,c[i]); // 操作する } ll ans = min(dp[n][1][0], dp[n][1][1]); cout << ans << endl; return 0; }
E - Paint
最後に操作したものは確定となるので、操作を後ろから見ていく
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' using ll = long long; int main() { int h,w,m; cin >> h >> w >> m; vector<tuple<int,int,int>> tp(m); REP(i,m) { int t,a,x; cin >> t >> a >> x; t--; a--; tp[i] = {t,a,x}; } const int mx = 2e5; const ll tot = (ll)h*w; vector<ll> col(mx+1); vector used(2,vector<int>(mx+1)); // 操作を後ろから見ていく reverse(tp.begin(),tp.end()); for(auto [t,a,x]: tp) { if (used[t][a]) continue; used[t][a] = 1; if (t == 0) { col[x] += w; h--; } else { col[x] += h; w--; } } ll sum = accumulate(col.begin(),col.end(),0LL); col[0] += tot - sum; // 初期の色0分を足す vector<pair<int,ll>> ans; REP(i,mx+1) if (col[i] > 0) ans.emplace_back(i,col[i]); cout << ans.size() << endl; for(auto [k,v]: ans) cout << k << " " << v << endl; return 0; }