[ABC227] D - Project Planning

[Q] https://atcoder.jp/contests/abc227/tasks/abc227_d

K=3の場合を考察し、法則を見つける。
1. Aを昇順sort。上位3つを選ぶ。
2. 下位の値を、上位3つに振り分けることを考える。
3. にぶたんで、最大プロジェクト数を探索する。

Q. K=3
3 5 5 5 を考える。
sortして 3 5 5 5

これは、

  3 5 5 5
  -------
- 1 1 1 0
- 1 0 1 1
- 1 1 0 1
  -------
  0 3 3 3

にしたあと、3 回とるのが最適だなと思う。

逆に、
  3 5 5 5
  =======
  ->1        // ふりわける
  --->1
  ----->1
  =======
  0 6 6 6 として、上位 3 つにバランスよく分ければいいと思う。


Q. K=3
1 1  1 1  1 1 10 を考える。

なんとなく、
  1 1  1 1  1 1 10
  ----------------
- 1 1  0 0  0 0 1
- 0 0  1 1  0 0 1
- 0 0  0 0  1 1 1
  ----------------
  0 0  0 0  0 0 7

3 が解答になりそう。

1. 上位3(K)と、それ以外の余剰ポイントを考える。
  1 1  1 1  1 1 10
            1 1 10 = A[]
  1 1  1 1 = 4point 

4point は、A[]のどこにでも振り分けられる。

2. にぶたん
作れるプロジェクト数 mid を探索する。
1) mid = 5 だとしたら、

  5 5 5
- 1 1 10
  ------
  4 4 0 // 8point 不足

8point > 4point なので、5 プロジェクトは不成立。

2) mid = 3 だとしたら、

  3 3 3
- 1 1 10
  ------
  2 2 0 // = 4point 不足
4point不足は補えるので、3 プロジェクトは成立。

そして解答は3

実装

int main(){
 cincout();
 
 ll N, K;
 cin >> N >> K;
 vector<ll> A(N);
 rep(i, N) cin >> A[i];
 sort(all(A));
 ll smalls = 0;
 rep(i, N-K){
   smalls += A[i]; // 振り分けられるポイント
 }
 
 ll B[K]; // 上位K項目
 rep(i, K) B[i] = A[N-1-i];

// にぶたん
 ll low = -1;
 ll high = oo+100;
 while (high-low > 1){
   ll mid = (high+low)/2;
   
   ll use = 0;
   bool ok=true;
   rep(i, K){
     use += max(0LL, mid-B[i]);
     if (use>smalls) ok = false;
   }
   if (ok) low = mid;
   else high = mid;
 }
 cout << low << endl;
}

https://atcoder.jp/contests/abc227/submissions/27224849

いいなと思ったら応援しよう!