Official

A - 照明の範囲 / Range of Illumination Editorial by physics0523 Editorial for printing


初心者の方へ


解法1 : \(R\) を全探索

\(-100 \le X_i \le 100\) なので、 \(R\) として \(0\) 以上 \(100\) 以下の整数をすべて考慮すれば十分です。この \(R\) を全探索することを考えます。

\(R\) を固定した際、 X[i] にある標識を証明が照らすかどうかは -R<=X[i] && X[i]<=R や abs(X[i])<=R といった方法で判定できます。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int N;
  cin >> N;
  vector<int> X(N),P(N);
  for(int i=0;i<N;i++){
    cin >> X[i] >> P[i];
  }
  int res=0;
  for(int R=0;R<=100;R++){
    int tot=0;
    for(int i=0;i<N;i++){
      if(abs(X[i])<=R){tot+=P[i];}
    }
    res=max(res,tot-R*R);
  }
  cout << res << "\n";
  return 0;
}

解法2: \(R\) の値域によらない解法

最適な \(R\) は、\(R=0\) であるか、ある標識をちょうど照らすような場合に限られることがわかります。
厳密には、 \(R=0\) であるか、ある \(i\) が存在して \(R=|X_i|\) が成り立つべきです。

標識を \(|X_i|\) の昇順に並べ替えておきます。このとき、列中で照らされる標識は列の中で前からいくつかという形になることが分かります。
ある座標 \(X_i\) にある標識までを照らした際、その標識、および並べ替えた列中でそれより前にある標識についての \(P_i\) の総和だけ効果が増加し、 \(|X_i|^2\) だけ効果が減少します。
\(|X_i|\) が同一である標識が複数ある場合の考慮はやや難しいですが、実は便宜上 \(|X_i|\) が異なるとみなして列中の先頭から特定の標識までを照らしたことにして求解して構いません。
また、実装例のように、 \(|X_i|\) が等しい標識たちをまとめて取り扱う ( \(P_i\) を当該標識の合計とみなす ) ような方法もあります。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int N;
  cin >> N;
  map<int,int> mp;
  for(int i=0;i<N;i++){
    int X,P;
    cin >> X >> P;
    mp[abs(X)]+=P;
  }
  int res=0,sum=0;
  for(auto &nx : mp){
    sum+=nx.second;
    res=max(res,sum-nx.first*nx.first);
  }
  cout << res << "\n";
  return 0;
}

posted:
last update: