-
초급반 3주차 풀이 - 반복문, 배열, 누적합ALOHA - 2022/ALOHA - 초급반 (2022 1학기) 2022. 5. 3. 10:15
A. [2438] 별 찍기 - 1 (Bronze III)
더보기반복문 예제로 항상 나오는 '별 찍기'에 왔습니다.
\( i \)번째 줄에는 별을 \( i \)개 찍어주면 됩니다.
void Main(){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ for (int j = 1; j <= i; j++){ printf("*"); } printf("\n"); } }
1. [2440] 별 찍기 - 3 (Bronze III)
더보기\( i \)번째 줄에는 별을 \( N-i+1 \)개 찍어주면 됩니다.
void Main(){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ for (int j = 1; j <= n-i+1; j++){ printf("*"); } printf("\n"); } }
더보기A. [2438] 별 찍기 - 1을 찍고, 이런 생각을 해봅시다. 'i를 n에서 1로 떨어뜨린다면?'
그럼 1. [2440] 별 찍기 - 3의 정답이 됩니다.
void Main(){ int n; scanf("%d", &n); for (int i = n; i >= 1; i--){ for (int j = 1; j <= i; j++){ printf("*"); } printf("\n"); } }
2. [4344] 평균은 넘겠지 (Bronze I)
더보기평균을 구한 뒤, 그 평균보다 큰 점수를 받은 학생의 수를 세주면 됩니다.
'크거나 같은'이 아님에 주의하세요.
int arr[1020]; void Main(){ int t; scanf("%d", &t); while (t--){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ scanf("%d", &arr[i]); } double avg = 0; for (int i = 1; i <= n; i++){ avg += arr[i]; } avg /= n; int cnt = 0; for (int i = 1; i <= n; i++){ if (avg < arr[i]){ cnt += 1; } } printf("%.3f%%\n", 100.0 * cnt/n); } }
3. [11659] 구간 합 구하기 4 (Silver IV)
더보기누적합으로 구해줄 수 있습니다.
\( PRF_{i} := \sum_{k=1}^{i} A_{k} \)로 두면, \( PRF_{i} = PRF_{i-1} + A_{i} \)이므로 계산도 빠르게 할 수 있고,
\( \sum_{k=l}^{r} A_{k} = PRF_{r} - PRF_{l-1} \)이니 문제의 답도 빠르게 구할 수 있습니다.
ll arr[100020], prf[100020]; void Main(){ int n, q; scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++){ scanf("%d", &arr[i]); } for (int i = 1; i <= n; i++){ prf[i] = prf[i-1] + arr[i]; } while (q--){ int l, r; scanf("%d %d", &l, &r); printf("%lld\n", prf[r] - prf[l-1]); } }
4. [2439] 별 찍기 - 2 (Bronze III)
더보기이번에는 오른쪽으로 정렬된 별을 찍어야 합니다... 또는 공백과 별을 같이 찍어야 합니다.
\( i \)번째 줄에는 공백 \( N-i \)개와 별 \( i \)개를 찍어주면 됩니다.
void Main(){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ for (int j = 1; j <= n-i; j++){ printf(" "); } for (int j = 1; j <= i; j++){ printf("*"); } printf("\n"); } }
5. [2442] 별 찍기 - 5 (Bronze III)
더보기\( i \)번째 줄에 찍어야 하는 공백은 \( N-i \)개입니다. (공백만 두고 보면 4. [2439] 별 찍기 - 2와 동일)
그리고 \( i \)번째 줄에 찍어야 하는 별은 \( 2i - 1\)개입니다. (문제에서 알려줌)
void Main(){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ for (int j = 1; j <= n-i; j++){ printf(" "); } for (int j = 1; j <= 2*i-1; j++){ printf("*"); } printf("\n"); } }
6. [2852] NBA 농구 (Silver III)
더보기일단 아래 배열들을 정의합시다.
\( A_{i} := \) 경기 시작 \( i \)초 후에 1번 팀이 골을 넣었는가?
\( B_{i} := \) 경기 시작 \( i \)초 후 2번 팀이 골을 넣었는가?
\( PA_{i} := \) 경기 시작 \( i \)초 후 1번 팀의 득점 상황
\( PB_{i} := \) 경기 시작 \( i \)초 후 2번 팀의 득점 상황
이제 득점이 들어올 때마다 그에 맞는 배열과 시간에 1을 더해둔 뒤,
입력이 끝났을 때 PA와 PB를 A와 B의 누적합으로 구해주면 됩니다.
1번 팀이 이기던 시간은 \( PA_{i} \gt PB_{i} \)인 \( i \)의 개수,
2번 팀이 이기던 시간은 \( PA_{i} \lt PB_{i} \)인 \( i \)의 개수로 구해줄 수 있습니다.
입력과 출력 과정이 약간 복잡함에 주의하세요. [TODO: C언어로 코드 작성]
const int T = 48*60; pi2 arr[T+20]; void prt(int t){ cout << t/600 << t/60%10 << ":" << t/10%6 << t%10; } void Main(){ int n; cin >> n; for (int i = 1; i <= n; i++){ int x; string t; cin >> x >> t; int m = (t[0]-'0')*10 + t[1]-'0'; int s = (t[3]-'0')*10 + t[4]-'0'; int tim = 60*m + s; for (int p = tim; p < T; p++){ if (x == 1){ arr[p].fr += 1; } else{ arr[p].sc += 1; } } } int t1 = 0, t2 = 0; for (int i = 0; i < T; i++){ if (arr[i].fr > arr[i].sc){ t1 += 1; } if (arr[i].fr < arr[i].sc){ t2 += 1; } } prt(t1); cout << endl; prt(t2); }
7. [2559] 수열 (Silver III)
더보기구간의 합을 구해야 하니 일단 누적합을 넣어봅시다.
\( PRF_{i} := \sum_{k=1}^{i} A_{k} \)
이제 답을 생각해봅시다.
연속적인 \( K \)일간의 온도의 합은 \( \sum_{p=i}^{i+K-1} A_{p} \)로 나타낼 수 있고,
\( \sum_{p=i}^{i+K-1} A_{p} = PRF_{i+K-1} - PRF_{i-1} \)로 나타낼 수 있습니다.
그러니 \( \max_{1 \le i \le i+K-1 \le N} (PRF_{i+K-1} - PRF_{i-1}) \)을 구해주면 됩니다.
int arr[100020], prf[100020]; void Main(){ int n, k; scanf("%d %d", &n, &k); for (int i = 1; i <= n; i++){ scanf("%d", &arr[i]); } for (int i = 1; i <= n; i++){ prf[i] = prf[i-1] + arr[i]; } int ans = -1e9; for (int i = 1; i+k-1 <= n; i++){ int res = prf[i+k-1] - prf[i-1]; if (ans < res){ ans = res; } } printf("%d", ans); }
8. [10211] Maximum Subarray (Silver III)
더보기일단 문제에서 주어진 식을 구간합을 사용하여 바꿔봅시다.
\( PRF_{i} := \sum_{k=1}^{i} A_{k} \)
\( \max_{1 \le i \le j \le N} (A_{i} + A_{i+1} + \cdots + \A_{j}) = \max_{1 \le i \le j \le N} (PRF_{j} - PRF_{i-1}) \)
이제 저대로 구현해주면 됩니다.
int arr[1020], prf[1020]; void Main(){ int t; scanf("%d", &t); while (t--){ int n, k; scanf("%d", &n); for (int i = 1; i <= n; i++){ scanf("%d", &arr[i]); } for (int i = 1; i <= n; i++){ prf[i] = prf[i-1] + arr[i]; } int ans = -1e9; for (int i = 1; i <= n; i++){ for (int j = i; j <= n; j++){ int res = prf[j] - prf[i-1]; if (ans < res){ ans = res; } } } printf("%d\n", ans); } }
더보기사실 이 문제는 누적합 없이도 풀 수 있습니다.
\( i \)에서 시작해서 \( j \)를 한 칸씩 옮길 때마다 합을 갱신해주고,
최종 답은 위 과정에서 나왔던 모든 합 중 하나가 됩니다.
int arr[1020]; void Main(){ int t; scanf("%d", &t); while (t--){ int n; scanf("%d", &n); for (int i = 1; i <= n; i++){ scanf("%d", &arr[i]); } int ans = -1e9; for (int i = 1; i <= n; i++){ int res = 0; for (int j = i; j <= n; j++){ res += arr[j]; if (ans < res){ ans = res; } } } printf("%d\n", ans); } }
9. [11660] 구간 합 구하기 5 (Silver III)
더보기이젠 2차원 누적합 문제입니다. 그러니 일단 누적합을 정의해봅시다.
\( PRF_{i, j} := \) \( \sum_{y=1}^{i} \sum_{x=1}^{j} A_{y, x} \)
위와 같이 저장하면 2차원 누적합은 그리 어렵지 않게 해결할 수 있는데, '포함-배제의 원리'를 사용하면 됩니다.
\( \sum_{y=y_{1}}^{y_{2}} \sum_{x=x_{1}}^{x_{2}} A_{y, x} = PRF_{y_{2}, x_{2}} - PRF_{y_{2}, x_{1}-1} - PRF_{y_{1}-1, x_{2}} + PRF_{y_{1}-1, x_{1}-1} \)
누적합을 직접 그려보면 간단히 이해할 수 있습니다. [TODO: 그림 추가]
이제 그대로 짜면 될 것 같지만, 위 정의대로 PRF를 구현했다가는 PRF 구하는 과정에서 TLE가 나게 됩니다.
그러니, \( PRF_{i, j} \)를 아래 식으로 구해줘야 합니다. (위에 있던 쿼리 식이랑 비교해보세요.)
\( PRF_{i, j} = A_{i, j} + PRF_{i, j-1} + PRF_{i-1, j} - PRF_{i-1, j-1} \)
ll arr[1030][1030], prf[1030][1030]; int main(){ int n, q; scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++){ for (int j = 1; j <= n; j++){ scanf("%d", &arr[i][j]); } } for (int i = 1; i <= n; i++){ for (int j = 1; j <= n; j++){ prf[i][j] = arr[i][j] + prf[i][j-1] + prf[i-1][j] - prf[i-1][j-1]; } } while (q--){ int y1, y2, x1, x2; cin >> y1 >> x1 >> y2 >> x2; y1 -= 1; x1 -= 1; printf("%lld\n", prf[y2][x2] - prf[y2][x1] - prf[y1][x2] + prf[y1][x1]); } }
'ALOHA - 2022 > ALOHA - 초급반 (2022 1학기)' 카테고리의 다른 글
초급반 6주차 풀이 - 구조체, STL (0) 2022.05.18 초급반 5주차 풀이 - DP, 시간복잡도 (0) 2022.05.10 초급반 4주차 풀이 - 함수, 재귀, DP (0) 2022.05.04 초급반 2주차 풀이 - 반복문, 배열, 문자열 (0) 2022.05.01 초급반 1주차 풀이 - 입출력, 연산자, 조건문 (0) 2022.04.29