SRM 679 Div2 Medium
TopCoder Statistics - Problem Statement
- 復習。復習。
- 問題文の意味がわからなくてタイムロスしてしまった。
- ある時間での勝者を探す。時間の範囲は 0~10^9 なので単純なループじゃ TLE するが、各 submit time とその前後 1 秒くらいだけ調べればよいので 3*n のループで済む。
- submit 数がどれくらなのかがちょっとわからないので、累積和を事前に計算して、二分探索によって高速化しておく。
- 本番時間ギリギリでサンプル通してサブミットしたのに system test で落ちた...。
- 原因は time == 0 のときの累積和計算を push_back していなかったから。
- 区間端のコーナーケースの処理忘れをしないように注意しよう。もったいなさすぎる。
class ContestScoreboard { public: vector <int> findWinner(vector <string> scores) { int n = scores.size(); vector<ll> ret(n,0); vector<string> names(n); vector<vector<pair<ll,ll>>> sbm(n); // vector<vector<pair<ll,ll>>> sum(n); vector<ll> time; // O(n) REP(i,n) { auto tokens = split(scores[i], " "); names[i] = tokens[0]; FOR(j,1,tokens.size()) { auto v = split(tokens[j],"/"); ll t,val; t = stoll(v[1]); val = stoll(v[0]); sbm[i].emplace_back(t,val); //sort by time // 探索対象となる時間は submit time とその前後 1 秒くらいでよい time.push_back(max(t-1,0LL)); time.push_back(t); time.push_back(max(t+1,0LL)); } sort(RANGE(sbm[i])); // 累積和を計算しておく ll s = 0; sum[i].emplace_back(0,0); // time == 0 のときを入れないとダメ REP(j,sbm[i].size()) { ll t,v; tie(t,v) = sbm[i][j]; s += v; sum[i].emplace_back(t,s); } } // 重複時間削除 sort(RANGE(time)); time.erase(unique(time.begin(), time.end()), time.end()); // O(n*3 * n * log(m)) vector<int> win(n,0); for (auto T : time) { int maxj = -1; string maxName="$"; ll maxScore = -1; REP(i,n) { auto idx = lower_bound(RANGE(sum[i]),make_pair(T,-1LL)) - sum[i].begin(); if (idx == 0) continue; ll val; tie(ignore,val) = sum[i][idx-1]; if ( val > maxScore || (val == maxScore && names[i] < maxName)) { maxj = i; maxName = names[i]; maxScore = val; } } if (maxj >= 0) win[maxj] = 1; } return win; } };