백준 10080 - 컬러볼

2 minute read

문제링크

문제설명

  • 특정한 색과 크기를 가진 공들이 주어진다.
  • i번 공을 가진 플레이어는 본인의 공과 색깔이 다르고 크기가 작은 다른 공들을 사로잡을 수 있다.
  • 공들의 색과 크기가 주어졌을 때, 각 플레이어들이 사로잡을 수 있는 모든 공들의 크기의 합을 출력하라

문제접근

  • N이 20만개, 크기가 1~2000 범위를 가지기 때문에 각 플레이어마다 공의 크기를 비교해가며 답을 구하는 것은 시간초과에 걸린다.
  • 공의 색깔, 크기, 인덱스 정보를 담을 수 있도록 구조체를 선언하고, 벡터 배열에 담는다.
    • 크기를 기준으로 오름차순 정렬을 하고, 크기가 같다면 색깔 번호를 기준으로 오름차순 정렬한다.
  • 각 플레이어가 가질 수 있는 모든 공들의 크기 합은 아래와 같다.
  • i번 공이 사로잡을 수 있는 공들의 크기 합 = 이전까지 쌓아온 크기의 합 - 같은 색깔을 가진 공들의 크기 합 - 같은 크기를 가진 공들의 크기 합
    • 이때, 색깔과 크기가 모두 같은 공이 여러 개 있을 수 있다. 만약, 이전에 탐색한 공과 현재 탐색하는 공이 색깔과 크기가 모두 동일하다면 위 공식은 중복된 뺄셈을 하게 된다.
    • 같은 색깔을 가진 공들의 크기 합 에는 같은 색깔이면서 크기도 동일한 공도 포함된다. 따라서 같은 크기를 가진 공들의 크기 합 을 뺄때 동일한 공을 중복해서 빼는 상황이 발생한다.
    • 따라서 위 공식은 동일한 크기의 공의 경우 색깔이 달라지는 처음 공에 한해서만 올바르게 동작한다.
  • 색깔과 크기가 모두 같은 공인 경우 이전에 구한 결과와 동일한 결과를 가지도록 설정해주어야 한다.

구현

#include <iostream>
#include <vector>
#include <algorithm>
#include <memory.h>
using namespace std;

typedef struct _ball {
	int color, size, idx;
} Ball;

vector<Ball> ballList;
int szColor[200001];
int answer[200001];
int sameSz[200001];

bool cmp(Ball b1, Ball b2) {
	if (b1.size != b2.size)
		return b1.size < b2.size;
	else
		return b1.color < b2.color;
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);
	
	int N;
	scanf("%d", &N);
	Ball iball;
	for (int i = 1; i <= N; i++) {
		scanf("%d %d", &iball.color, &iball.size);
		iball.idx = i;
		ballList.push_back(iball);
	}
	// 크기와 색깔 번호가 작은 공부터 사로잡을 수 있는 공들을 찾는다.
	sort(ballList.begin(), ballList.end(), cmp);

	memset(szColor, 0, sizeof(szColor));
	memset(answer, 0, sizeof(answer));
	memset(sameSz, 0, sizeof(sameSz));
	int sum = 0;
	for (int i = 0; i < ballList.size(); i++) {
		int color = ballList[i].color;
		int sz = ballList[i].size;
		int idx = ballList[i].idx;

		answer[idx] = sum - szColor[color] - sameSz[sz];
		// 색깔, 크기가 동일한 공의 경우 이전 공과 같은 결과를 담는다.
		if (i > 0 && (ballList[i - 1].color == color) && (ballList[i - 1].size == sz))
			answer[idx] = answer[ballList[i - 1].idx];

		sum += sz;
		szColor[color] += sz; // 색깔이 같은 공들의 무게 합
		sameSz[sz] += sz; // 크기가 같은 공들의 무게 합

		
	}
	for (int i = 1; i <= N; i++) 
		printf("%d\n", answer[i]);
}

Leave a comment