2차원 좌표평면에 K개의 무선장치가 달려 있으며, 각 무선 장치는 반지름이 R_i인 원 형태의 범위에 B_i의 세기로 신호를 쏴준다.
Bob은 한 번에 여러 신호를 수신할 수 있으며 각각의 신호의 세기는 더할 수 있을 때, Bob이 수신할 수 있는 신호의 최대 세기를 구하고, 그러한 정수 좌표의 개수를 구하는 문제이다.

이 그림은 예제 1의 그림이며, 신호 세기가 12인 곳을 표시한 것이다.
얼마전에 푼 #3552번이 생각났다.
모든 정수 좌표에 대해 원과의 교점을 구하고 그 점에서의 신호 세기를 구하면 O(NMK)로 TLE가 발생한다. 따라서, 스위핑으로 x축을 훑으며 원과의 교점을 빠르게 구하자.

C++ 연습 겸 C++23으로 풀었다. 앞으로도 웬만한 문제는 C++로 풀듯?
아직 덜 익숙해서 그런가 디버깅이 꽤 힘들었다.
// 백준 6818
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
struct Circle {
int x, y, r, bitrate;
};
vector<Circle> circles;
// 원 C가 x=a와의 정수 교점 범위 반환
pair<int, int> cross(Circle c, int a) {
double dist = sqrt(c.r*c.r-(c.x-a)*(c.x-a));
return {(int)ceil(c.y-dist), (int)(c.y+dist)};
}
pair<int, int> solve(int X, int Y, int K) {
int maxBitrate = 0;
int maxCount = 0;
vector<int> diff(Y+2, 0);
for (int x=1; x<=X; x++) {
fill(diff.begin(), diff.end(), 0);
// 모든 원에 대해 포함 범위 계산
for (const Circle& c : circles) {
if (x < c.x-c.r || x > c.x+c.r) continue;
// 원의 포함 범위를 차분 배열에 저장
auto [startY, endY] = cross(c, x);
startY = max(1, startY);
endY = min(Y, endY);
diff[startY] += c.bitrate;
if (endY < Y) {
diff[endY+1] -= c.bitrate;
}
}
// 차분 배열에서 최대값 추출
int accSum = 0;
int totalCount = 0;
int diffMax = 0;
for (int i=1; i<=Y; i++) {
accSum += diff[i];
if (diffMax < accSum) {
totalCount = 1;
diffMax = accSum;
}
else if (diffMax == accSum)
totalCount += 1;
}
// 이전 x좌표에서의 최대값과 비교 및 갱신
if (maxBitrate < diffMax) {
maxCount = totalCount;
maxBitrate = diffMax;
}
else if (maxBitrate == diffMax)
maxCount += totalCount;
}
return {maxBitrate, maxCount};
}
int main() {
cin.tie(0);
ios_base::sync_with_stdio(0);
int X, Y, K;
cin >> Y >> X >> K;
circles.resize(K);
for (int i=0; i<K; i++)
cin >> circles[i].x >> circles[i].y >> circles[i].r >> circles[i].bitrate;
pair<int, int> result = solve(X, Y, K);
cout << result.first << '\n' << result.second << '\n';
}