TCO2012 Round2C Hard FlattenOut
問題
n個の土地が円周上に並んでいる。
それぞれの土地の高さはheight[i]である。
この土地に対して次のような操作をT回行う。
heightが正であるような土地i全てについて、height[i]を1減らし、height[(i + 1) % n]を1増やす。
この操作は全て同時に行われる。
操作を終えた時点でのそれぞれの土地の高さを求めよ。
制約条件
n≦50
T≦10^16
-10^16≦height[i]≦10^16
方針
シミュレートするだけ。
全ての土地の高さが正になってたら、もう更新はない。
全ての土地の高さが0以下でも更新はないので終了する。
全ての土地の高さが0または1だったらT % n右にシフトするだけ。
それ以外の場合、
正, 正, ..., 正, 負という列で、最初の正が最後の負を埋めることになる。
すると、正の土地または負の土地の数が必ず一つ減るので、
この操作は50回程度で終了することがわかるので、愚直にシミュレートすればいい。
ソースコード
class FlattenOut { public: vector<long long> simulateIt(vector<long long> height, long long T) { int n = height.size(); while(T){ bool posi = 0, nega = 0, zeroone = 1; rep(i, n){ if(height[i] > 0) posi = 1; else nega = 1; if(height[i] != 0 && height[i] != 1) zeroone = 0; } if(!posi || !nega) return height; if(zeroone){ if(T % n) rotate(height.begin(), height.begin() + n - T % n, height.end()); return height; } ll mn = T; vector<pi> ps; rep(i, n) if(height[i] <= 0 && height[(i + 1) % n] > 0){ int j = 0; for(; j < n; j++) if(height[(i + 1 + j) % n] <= 0) break; ps.pb(mp((i + 1) % n, j)); mn = min(mn, -height[(i + j + 1) % n] + 1); mn = min(mn, height[(i + 1) % n]); } rep(i, ps.size()){ int a = ps[i].first, b = ps[i].second; height[a] -= mn; height[(a + b) % n] += mn; } T -= mn; } return height; } };