Skip to content

Commit

Permalink
Merge pull request #108 from donghoony/patch-2
Browse files Browse the repository at this point in the history
week14 donghoony
  • Loading branch information
hjk0761 authored Aug 5, 2024
2 parents 7f344af + 51d30a0 commit f9fcdeb
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 8 deletions.
5 changes: 5 additions & 0 deletions week14/A_28422/donghoony/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
[Link](https://boj.kr/28422)
## 💡 풀이 방법 요약

`f(x)`: `x` 번째부터 카드를 2, 3장 뽑았을 때 얻을 수 있는 최대 점수
base: `x > N`이거나 전체 카드가 한 장뿐일 때 -> `1`
step: 만약 `f(x+2), f(x+3)`이 잘 구해준다면, 현재 `위쪽 두 장 XOR + f(x+2)` 혹은 `위쪽 세 장 XOR + f(x+3)` 중 큰 것이 답.

## 👀 실패 이유
폰코딩으로 풀어서 두 번 틀렸습니다

## 🙂 마무리
26 changes: 26 additions & 0 deletions week14/A_28422/donghoony/sol.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <bits/stdc++.h>
using namespace std;
constexpr int INF = 0x3f3f3f3f;
typedef long long ll;

ll N, arr[101010], d[101010];

ll f(int x) {
if (x > N || N == 1) return 0;
ll& ret = d[x];
if (ret != -1) return ret;
ret = -INF;

if (x <= N-2)
ret = max(ret, f(x+3) + __builtin_popcount(arr[x] ^ arr[x+1] ^ arr[x+2]));
if (x <= N-1)
ret = max(ret, f(x+2) + __builtin_popcount(arr[x] ^ arr[x+1]));
return ret;
}

int main(){
memset(d, -1, sizeof d);
cin >> N;
for (int i = 1; i <= N; i++) cin >> arr[i];
cout << f(1) << endl;
}
10 changes: 8 additions & 2 deletions week14/B_1885/donghoony/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Info
[Link](https://boj.kr/1885)
## 💡 풀이 방법 요약

## 👀 실패 이유
- 길이가 mid인 모든 수열 중 주어진 수열의 부분수열이 아닌 게 존재하는가? -> NNN...NYYYY 꼴이므로 처음 Y가 되는 부분을 찾아 문제를 해결할 수 있다
- 다만 이분 탐색이 아니더라도, 몇 가지 관찰을 통해 알아낼 수 있다.
- `1 2 3`, `K=4`이면 `4` 부분수열이 존재하지 않으므로 답은 `1`
- `1 2 3 2 1`, `K=3`이면 `3 3` 부분수열이 존재하지 않으므로 답은 `2`, 이를 `3`으로 만들기 위해서는 `3`을 추가해야 한다.
- `1 ~ K`가 모두 존재하는 구간으로 쪼개야 한다.
- 쪼갠 뒤, 구간의 개수 + 1이 정답이다. 구간의 개수까지는 모든 수열이 등장한다고 할 수 있다.
- `1 2 3 1 2 3 1 2 3 4`, `K=4`이면 `4 4`가 존재하지 않으므로.. 답은 2. 그래서 `1 ~ K`가 모두 등장하는 구간으로 쪼개야 한다.

## 🙂 마무리
set을 사용하는 logN 풀이에서 토글링을 사용하는 N 풀이가 재미있다. (28ms -> 4ms)
17 changes: 17 additions & 0 deletions week14/B_1885/donghoony/sol.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int N, K, cnt, ans, v[10001], t, f = 1;

int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> N >> K;
while (N--) {
cin >> t;
if (f ^ v[t]) v[t] = f, cnt++;
if (cnt == K) ans++, cnt = 0, f = !f;
}
cout << ans + 1 << '\n';
return 0;
}
7 changes: 5 additions & 2 deletions week14/C_1464/donghoony/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Info
[Link](https://boj.kr/1464)
## 💡 풀이 방법 요약

## 👀 실패 이유
- 앞에서부터 뒤집을 수 있음에 집중하자. 문자를 앞에서 봐도 되는 것과 비슷한 맥락일 수 있다.
- ACAB -> CAAB -> AACB, AABC로 만들 수는 없다.
- 앞에서부터 보면서 뒤집을지, 말지를 선택할 수 있다
- A -> AC -> (A)AC (뒤집음) -> AACB

## 🙂 마무리
이게 B보다 쉬웠어요
22 changes: 22 additions & 0 deletions week14/C_1464/donghoony/sol.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
constexpr int INF = 0x3f3f3f3f;
constexpr ll MOD = 1e9;

string s;
deque<char> dq;

int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> s;
dq.push_back(s[0]);
for (int i = 1; i < s.length(); i++) {
if (dq.front() >= s[i]) dq.push_front(s[i]);
else dq.push_back(s[i]);
}
for (auto& c : dq) cout << c << "";
cout << '\n';
return 0;
}
12 changes: 12 additions & 0 deletions week14/C_1464/donghoony/sol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import sys
from collections import deque

s = input()
dq = deque()
dq.append(s[0])
for c in s[1:]:
if dq[0] >= c:
dq.appendleft(c)
else:
dq.append(c)
print(*dq, sep="")
11 changes: 7 additions & 4 deletions week14/D_31778/donghoony/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Info
[Link](https://boj.kr/31778)
## 💡 풀이 방법 요약

## 👀 실패 이유

## 🙂 마무리
- 최대 `K`번 스왑할 수 있음, PPC 부분문자열을 최대한으로 만들어야 함
- 간단하게 생각하면 P를 가장 앞으로, C를 맨 뒤로 옮겨야 함. 그리고 이 그리디가 옳다.
- 만약 가장 뒤의 P가 아닌 다른 P를 이동해 PPC 부분문자열을 최대한으로 만드는 해가 있다고 하자.
- 그렇다면 해당 `P`(i)보다 뒤에 존재하는 `P`(j)가 있을 것이다. `(i < j)`
- `i < j`이고 `i``j` 사이에 `P`가 존재한다면, 더 좋은 해가 나오므로 모순이다.
- 존재하지 않는다면, 처음에 생각한 해와 답이 같게 나오므로 바꿔도 무관하다.
- 같은 방식으로 C에도 적용할 수 있으며, 가장 앞의 C와 가장 뒤의 P를 바꾸는 것을 반복하면 된다.
27 changes: 27 additions & 0 deletions week14/D_31778/donghoony/sol.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
constexpr int INF = 0x3f3f3f3f;
constexpr ll MOD = 1e9;

ll N, K, ans, p_cnt;
string s;
vector<int> c, p;

int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> N >> K >> s;
for (int i = 0; i < s.length(); i++) {
if (s[i] == 'C') c.push_back(i);
else p.push_back(i);
}
for (int i = 0, j = p.size() - 1; i < min({c.size(), p.size(), (size_t) K}) && c[i] < p[j]; i++, j--)
swap(s[c[i]], s[p[j]]);
for (auto ch : s) {
if (ch == 'P') { p_cnt++; continue; }
ans += p_cnt * (p_cnt - 1) / 2;
}
cout << ans << '\n';
return 0;
}

0 comments on commit f9fcdeb

Please sign in to comment.