A - 照明の範囲 / Range of Illumination Editorial
by
physics0523
Editorial for printing
初心者の方へ
- AtCoder をはじめたばかりで何をしたらよいか分からない方は、まずは practice contest の問題A「Welcome to AtCoder」を解いてみてください。基本的な入出力の方法が載っています。
- また、プログラミングコンテストの問題に慣れていない方は、AtCoder Beginners Selection の問題をいくつか解いてみることをおすすめします。
- C++入門 AtCoder Programming Guide for beginners (APG4b) は、競技プログラミングのための C++ 入門用コンテンツです。
- Python入門 AtCoder Programming Guide for beginners (APG4bPython) は、競技プログラミングのための Python 入門用コンテンツです。
解法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:
