문제 출처

1. 문제설명


  • 스위치의 상태는 0(꺼짐) 또는 1(켜짐)로 부여된다.
  • 성별과 받은 수에 따라 스위치를 조작한다.
    • 남학생은 받은 번호의 배수인 스위치의 상태를 바꾼다.
      • 켜져 있으면 끄고, 꺼져 있으면 켠다.
    • 여학생은 자신의 번호를 중심으로 상태가 대칭인 지점까지 스위치를 바꾼다.



2. 알고리즘 설계


  • 처음 이해를 잘못했던 게 아래 문구 때문이었다.
    • 같은 번호가 붙은 스위치를 중심으로 좌우가 대칭이면서 가장 많은 스위치를 포함하는 구간을 찾아서,
    • 가장 많은 스위치를 포함하는 대칭 구간을 찾아야 하는 줄 알았다.
    • 예를 들어서, 받은 번호가 3이라고 해보자.
      • 3을 중심으로 [4,5]가 대칭이고,
      • 좌우 약 10칸 떨어진 구간에 대칭 스위치가 3개인 구간이 있다면?
      • [4,5]만 바꾸면 된다.
    • 본인이 하고 싶은 말은, 스위치를 중심으로 라는 문구를 잘 확인해야 한다는 것이다.



3. 로직


  • 남학생의 구현은 매우 간단하다.
    • cur_switch = !cur_switch;
    • 0 또는 1이므로, 간단하게 구현 가능하다.
    • if-else 문을 쓰지말자
  • 여학생 구현
    • 자기 번호 위치의 스위치는 무조건 상태가 바뀐다.
    • 스위치 번호의 -i, +i번째가 같아질 때까지 스위치의 상태를 바꾼다.
    • 다르다면, 즉시 종료한다.



4. 전체 코드


#include <bits/stdc++.h>
using namespace std;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);

	int n; cin >> n;
	vector<int> v(n + 1);

	for (int i = 1; i <= n; i++)
		cin >> v[i];

	int std_num; cin >> std_num;
	for (int i = 0; i < std_num; i++) {
		int sex, switch_num;
		cin >> sex >> switch_num;


		if (sex == 1) {
			for (int i = switch_num; i <= n; i += switch_num)
				v[i] = !v[i];
		}
		else {
			v[switch_num] = !v[switch_num];

			for (int i = 1; v[switch_num - i] == v[switch_num + i]; i++) {
				if (switch_num + i > n || switch_num - i < 1) break;
				v[switch_num - i] = !v[switch_num - i];
				v[switch_num + i] = !v[switch_num + i];
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		cout << v[i] << " ";
		if (i % 20 == 0) cout << "\n";
	}
	
	return 0;
}



5. 소감


  • 정답률 19%(2023-06-04 기준)로 극악인 문제인줄 알았는데,
  • 생각보다 간단한 문제라서 당황했다.
  • 아마 내 생각에는 여학생 스위치 바꾸는 구현에서 많이 틀리지 않았을까 싶다.