KAJIMA CORPORATION CONTEST 2024(AtCoder Beginner Contest 340) - AtCoder
B - Append
問題文をそのまま実装
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<n;i++) #define endl '\n' int main() { int q; cin >> q; vector<int> v; while(q--) { int t,x; cin >> t >> x; if (t == 1) v.push_back(x); else cout << v[v.size() - x] << endl; } return 0; }
C - Divide and Divide
メモ化DFS
#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() { ll n; cin >> n; map<ll,ll> memo; auto dfs = [&](auto self, ll x) -> ll { if (x < 2) { return 0LL; } if (memo.count(x)) return memo[x]; return memo[x] = x + self(self, x/2) + self(self, (x+1)/2); }; cout << dfs(dfs, n) << endl; return 0; }
D - Super Takahashi Bros.
重み付き有向グラフにしてダイクストラ
#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; using P = pair<ll,int>; const ll LINF = numeric_limits<ll>::max(); struct Edge { int to, cost; Edge(int to, int cost): to(to), cost(cost) {} }; int main() { int n; cin >> n; vector g(n,vector<Edge>()); REP(i,n-1) { int a,b,x; cin >> a >> b >> x; x--; g[i].emplace_back(i+1,a); g[i].emplace_back(x,b); } vector<ll> dist(n,LINF); priority_queue<P, vector<P>, greater<P>> q; auto push = [&](ll cost, int to) { if (dist[to] <= cost) return; dist[to] = cost; q.emplace(dist[to], to); }; push(0,0); while (q.size()) { auto [cost,v] = q.top(); q.pop(); if (dist[v] != cost) continue; for (Edge e: g[v]) push(dist[v]+e.cost, e.to); } cout << dist[n-1] << endl; return 0; }
E - Mancala 2
周期を考えて累積和する。累積和を毎回集計するため Fenwick Tree で高速化した
#include <bits/stdc++.h> #include <atcoder/all> using namespace atcoder; 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,m; cin >> n >> m; vector<int> a(n),b(m); REP(i,n) cin >> a[i]; REP(i,m) cin >> b[i]; fenwick_tree<ll> fw(n+1); // 累積和 REP(i,m) { ll t = fw.sum(0,b[i]+1); ll now = a[b[i]] + t; ll r = now / n; // 何周するか ll rem = now % n; // r周した余り分 a[b[i]] = 0; fw.add(b[i],-t); fw.add(b[i]+1,t); fw.add(0,r); if (b[i] + rem < n) { fw.add(b[i]+1,1); fw.add(b[i]+rem+1,-1); } else { fw.add(b[i]+1,1); fw.add(0,1); fw.add((rem+b[i])%n+1, -1); } } REP(i,n) cout << (ll)a[i] + fw.sum(0,i+1) << " "; return 0; }
今回はここまで