ABCDを解いた. 1968->1999(+31)でhighest.
A. Jumping Ball
解法
左から '<' が何個連続しているか, また右から '>' が何個連続しているかを数えれば良い.
ソース
#include <bits/stdc++.h> using namespace std; int main() { string S; int N; int ret = 0; cin >> N; cin >> S; for(int i = 0; i < S.size(); i++) { if(S[i] == '<') ++ret; else break; } for(int i = S.size() - 1; i >= 0; i--) { if(S[i] == '>') ++ret; else break; } cout << ret << endl; }
B. Food on the Plane
解法
気合い.
ソース
英語が読めない><
#include <bits/stdc++.h> using namespace std; typedef long long int64; string t = "fedabc"; int main() { int64 N; char c; scanf("%lld%c", &N, &c); int pos = t.find(c); int64 roll = (N - 1) / 2; if((N - 1) % 4 == 1) ++roll; else if((N - 1) % 4 == 2) --roll; if((N - 1) % 4 < 2) { cout << roll * 6 + pos + 1 + (N - 1) << endl; } else { cout << roll * 6 + pos + 1 + (N - 3) << endl; } }
C. Hidden Word
問題概要
文字からなるアルファベット列 が与えられる. 各アルファベットは少なくとも 回含まれることが保証される.
のパスが存在するような のグリッドが存在すればそれを出力せよ.
ここでパスはサイドかコーナーで隣接しているマスの間を移動してできる経路のことをいう.
解法
よくわからなかったので, 全探索をしてしまった.
流石に全探索だと遅いのでちょっと考察.
斜めに移動することが可能なので, 上下のアルファベットは入れ替えても一緒. よって例えば右と右下が開いているとき, 試すのは右だけで良い.
これだけやればなんか速かった.
ソース
#include <bits/stdc++.h> using namespace std; int dy[] = {-1, -1, -1, 0, 1, 1, 1, 0}, dx[] = {-1, 0, 1, -1, -1, 0, 1, 1}; string S; char grid[2][13]; bool used[26]; bool isover(int x, int y) { return (x < 0 || y < 0 || x >= 13 || y >= 2); } bool solve(int idx, int x, int y) { if(idx == S.size()) { return (true); } else if(used[S[idx] - 'A']) { for(int i = 0; i < 8; i++) { int nx = x + dx[i], ny = y + dy[i]; if(isover(nx, ny)) continue; if(grid[ny][nx] == S[idx]) return (solve(idx + 1, nx, ny)); } } else { used[S[idx] - 'A'] = true; if(grid[y ^ 1][x] == 0) { grid[y ^ 1][x] = S[idx]; if(solve(idx + 1, x, y ^ 1)) return (true); grid[y ^ 1][x] = 0; } if(!isover(x + 1, y) && grid[y][x + 1] == 0) { grid[y][x + 1] = S[idx]; if(solve(idx + 1, x + 1, y)) return (true); grid[y][x + 1] = 0; } else if(!isover(x + 1, y ^ 1) && grid[y ^ 1][x + 1] == 0) { grid[y ^ 1][x + 1] = S[idx]; if(solve(idx + 1, x + 1, y ^ 1)) return (true); grid[y ^ 1][x + 1] = 0; } if(!isover(x - 1, y) && grid[y][x - 1] == 0) { grid[y][x - 1] = S[idx]; if(solve(idx + 1, x - 1, y)) return (true); grid[y][x - 1] = 0; } else if(!isover(x - 1, y ^ 1) && grid[y ^ 1][x - 1] == 0) { grid[y ^ 1][x - 1] = S[idx]; if(solve(idx + 1, x - 1, y ^ 1)) return (true); grid[y ^ 1][x - 1] = 0; } used[S[idx] - 'A'] = false; } return (false); } void Output() { for(int i = 0; i < 2; i++) { for(int j = 0; j < 13; j++) { cout << grid[i][j]; } cout << endl; } exit(0); } int main() { cin >> S; for(int i = 0; i < 12; i++) { grid[0][i] = S.front(); used[S.front() - 'A'] = true; if(solve(1, i, 0)) Output(); grid[0][i] = 0; used[S.front() - 'A'] = false; } cout << "Impossible" << endl; }
D. Contest Balloons
問題概要
チームがあって から までの番号がつけられている.
各チームは風船を 個持っていて, チームの体重合計は である.
風船の個数が多い順に順位が振られる. 風船の個数が同じ場合は同順位である. また, 風船の個数が体重合計を上回ると浮かんでしまうので失格となる.
チーム は自分のチームである. 自分が持っている風船を任意個数相手のチームにあげることができる. このときチーム がとることできる最高順位を求めよ.
解法
問題文が面白い.
任意のチーム において, 個の風船を渡せば失格になる. 以降この数を とおく.
今の順位から順位を つ上げることを考える.
"自分より多く風船を持つチーム" のうち が最小のチームを失格にさせるのが最も効率的.
個のバルーンを渡すと, もともと "自分より風船が少なかったチーム" が上に来る. このチームたちを "自分より多く風船が持つチーム" に加える必要がある. 自分の風船の数は単調減少なので, "自分より風船が少なかったチーム" を風船の数で降順ソートしておけば, これに該当するチームは尺取りっぽく無駄なく抽出できる.
また結局, "自分より多く風船が持つチーム" に対してやりたいことは以下 つ.
- もともと自分より風船が少なかったチームを, これに加える.
- が最小のチームを取り出す.
これには値の追加, 最小要素の取り出しが で出来る優先度付きキューが適している.
以上の, 順位を つ上げる操作を自分の風船がある間繰り返すと良い.
全体で なので間に合う.
ソース
#include <bits/stdc++.h> using namespace std; typedef long long int64; int N; int64 T[300000], W[300000]; int check() { priority_queue< int64, vector< int64 >, greater< int64 > > highdist; vector< pair< int64, int > > lowidx; for(int i = 1; i < N; i++) { if(T[0] >= T[i]) lowidx.emplace_back(T[i], W[i] - T[i] + 1); else highdist.push(W[i] - T[i] + 1); } sort(begin(lowidx), end(lowidx)); reverse(begin(lowidx), end(lowidx)); int ret = highdist.size() + 1, tail = 0, odd = T[0]; while(!highdist.empty()) { int64 val = highdist.top(); highdist.pop(); odd -= val; if(odd < 0) return (ret); while(tail < lowidx.size() && odd < lowidx[tail].first) { highdist.push(lowidx[tail].second); ++tail; } ret = min< int >(ret, highdist.size() + 1); } return (ret); } int main() { scanf("%d", &N); for(int i = 0; i < N; i++) { scanf("%d %d", &T[i], &W[i]); } printf("%d\n", check()); }