Aising Programming Contest 2022(AtCoder Beginner Contest 255) - AtCoder
B - Light It Up
Bにしては難しい
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<(n);i++) int main() { int n,k; cin >> n >> k; vector<int> a(k),x(n),y(n); REP(i,k) { cin >> a[i]; a[i]--; } REP(i,n) cin >> x[i] >> y[i]; double ans = 0; REP(i,n) { double now = 1e6; for(int j: a) { double dx = x[i]-x[j]; double dy = y[i]-y[j]; now = min(now, sqrt(dx*dx + dy*dy)); } ans = max(ans,now); } printf("%0.10f\n", ans); return 0; }
C - ±1 Operation 1
Xが初項から末項の間かどうかで場合分けして考える。
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<(n);i++) using ll = long long; int main() { ll x,a,d,n; cin >> x >> a >> d >> n; x -= a; ll left, right; if (0 < d) { left = 0; right = d*(n-1); } else { left = d*(n-1); right = 0; } ll ans = min(abs(x-left), abs(x-right)); if (d != 0 && left <= x && x <= right) { ll m = abs(x) % abs(d); ans = min(ans, m); ans = min(ans, abs(d) - m); } cout << ans << endl; return 0; }
二分探索による別解
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<(n);i++) using ll = long long; int main() { ll x,a,d,n; cin >> x >> a >> d >> n; if (d < 0) { a = a + d * (n-1); d = -d; } ll l = 0, r = n-1; while(abs(r-l) > 1) { ll mid = (r+l)/2; if (a + d * (mid) < x) l = mid; else r = mid; } ll ans = abs(x - (a + d * l)); if (l < n-1) ans = min(ans, abs(x - (a + d * (l+1) ))); cout << ans << endl; return 0; }
D - ±1 Operation 2
- Aをソートする
- Xより大きくなるAのindexを二分探索で求める
- Aの累積和を取っておくと、X以下の合計とXより大きい部分の合計をO(1)で求められるので、それぞれの差分を合算することで必要な最小の操作回数を求められる
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<(n);i++) using ll = long long; int main() { int n,q; cin >> n >> q; vector<int> a(n); REP(i,n) cin >> a[i]; sort(a.begin(), a.end()); vector<ll> m(n+1); // 累積和 REP(i,n) m[i+1] = m[i]+a[i]; REP(i,q) { ll x; cin >> x; auto it = upper_bound(a.begin(), a.end(), x); int idx = it - a.begin(); // xより大きい最も左側のindex ll d1 = m[idx] - m[0]; // x以下の部分の累積和 ll ans = x * idx - d1; ll d2 = m[n] - m[idx]; // xより大きい部分の累積和 ans += d2 - x * (n - idx); cout << ans << endl; } return 0; }