no image
[백준-17135] 캐슬디팬스
시뮬레이션 + 백트래킹 문제이다. 1차적으로 궁수 3명을 N+1 번째 행에 3명을 조합의 경우의 수로 세워둔다. 그 다음 2차적으로 시간을 N까지 증가시키면서 적들을 아래 칸으로 한칸씩 움직이도록 한다. 3차적으로 한 칸씩 움직인 적들 중 각 궁수에게 가장 가까운, 거리가 같다면 제일 왼쪽에 있는 놈을 찾는 O(NlogN) 로직을 짜준다. 그 후 하나하나 죽이면서 죽는 놈들을 세어주면 된다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #define MAX_NUM 1000000009 using namespace std; typedef long long LL; typ..
2021.10.03
no image
[백준-3020] 개똥벌레
해당 높이에 몇개의 장애물이 있는지 누적합을 사용하는 문제이다. +-prefix 를 사용하여 어디서부터 어디까지 +인지 체크해주면 간단하게 누적합을 구할 수 있으며, O(N)의 복잡도로 문제를 풀 수 있다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include using namespace std; typedef long long LL; int sum[500001]; int main() { int n, m, a, b, c; scanf("%d %d", &n, &m); for (int i = 1; i
2021.10.01
no image
[백준-14391] 종이조각
백트래킹 문제이다. 일단 2차원 위치를 하나의 num으로 두고 나머지와, 몫으로 좌표를 설정하도록 한다. 그 후 하나씩 돌아가면서 해당 수만 직사각형 종이에 포함할 것인가 해당 수의 아래를 직사각형 종이에 포함할 것인가 해당 수의 오른쪽을 직사각형 종이에 포함할 것인가 를 하나씩 처리해주면서 문제를 풀면 간단하다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include using namespace std; // 입력값이 100만 -> nlogn 으로 끝내야 한다. int arr[5][5]; int check[5][5]; int dx[] = { -1, 0 }; int dy[] ..
2021.10.01
no image
[백준-19951] 태상이의훈련소생활
+-누적합 문제이다. 값의 변경을 일일이 배열에 체킹해주면 터지게 된다. 때문에 이를 +-누적합을 통해 구해줄 수 있다. ground : 첫 값이 들어가있는 배열 arr : "+ -" 체킹 배열 sum : 최종적으로 몇 만큼 변경해야하는지 들어있는 배열 #include using namespace std; typedef long long LL; int sum[100001]; int arr[100002]; int ground[100002]; int main() { int n, m, a, b, c; scanf("%d %d", &n, &m); for (int i = 1; i
2021.09.30
no image
[백준-10800] 컬러볼
20만의 입력값에 대응하기 위해 nlogn 또는 n의 복잡도로 문제를 풀어야 한다. 이를 위해 누적합을 통해 문제를 풀 수 있다. 다만 전체 합에 대한 누적합과 각 색상에 대한 누적합을 따로 구하여 해당 값을 처리해주면 된다. 이를 2가지 방법으로 구현하였다. 각 색상에 대한 누적합을 구해놓고, 각각의 답을 구할 시에 이분탐색을 돌린다. 모든 명령어를 정렬한 뒤 색에 대한 누적합과 전체에 대한 누적합을 동시에 진행해준다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include using namespace std; typedef long long LL; typedef pair pii; LL input; LL arr[2001]; LL all_..
2021.09.30
no image
[백준-10986] 나머지 합
누적합과 조합 계산식이 필요한 문제다. 일단 입력값을 보면 100만임을 봐서 최소 O(NlogN) 의 복잡도 내로 끝내야 함을 알 수 있다. 허나 이 문제의 경우 각 누적합을 통해 O(N) 복잡도로 끝낼 수 있다. 로직은 다음과 같다. 입력되는 배열을 순서대로 sum 배열에 넣되 m으로 나눈 나머지 값을 쭉 넣어준다. sum 배열을 순회하면서 원소를 pai 배열에 체킹해준다. pai 배열에 체킹된 순서로 순회하면서 조합식을 더하면 답이 된다. 이렇게 pai 배열을 둔 이유는 sum[i] - sum[j] = 0 이 되는 경우의 수를 찾아야 하는데 결국 sum[i] == sum[j] 인 경우를 찾는 것과 다름이 없다. 따라서 같은 값을 가지는 sum 배열의 원소들을 쭉 체킹해준 다음 nC2의 조합식에 따라 ..
2021.09.29
no image
[백준-11659]구간합구하기4
구간합을 구하는 간단한 문제였다. 세그먼트 트리 나 누적합 으로 풀면 간단하게 풀린다. 누적합 로직은 다음과 같다. (a~b)의 합 = b까지의 합 - (a-1)까지의 합 코드는 두가지 버전으로 작성해보았다. // 세그먼트 트리 로직 #include using namespace std; typedef long long LL; LL tree[300000]; LL query(int node, int s, int e, int l, int r) { if (e < l || r < s) return 0; if (l
2021.09.29
no image
[백준-15724] 주지수
카카오 6번 효율성 에 대해 검색하던 중 찾은 누적합 문제이다. 비슷하게 좌표를 통해 2차원 DP로 푸는 문제이다. 로직은 다음과 같다. (i,j) 까지의 누적합 = (i,j)의 값 + (i-1,j)까지의 누적합 + (i,j-1)까지의 누적합 - (i-1,j-1) 까지의 누적합 #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #define MAX_NUM 1000000009 using namespace std; typedef long long LL; typedef pair pii; int arr[1300][1301]; int main() { int row, col, a;..
2021.09.28
no image
[백준-2473] 세 용액
약간의 기술이 필요한 투 포인터 문제였다. 일단 기본적으로 5000의 입력값에 1초의 제한시간이기 때문에 O(N^2) 의 복잡도까지는 잘 통과할 것이다. O(N*NlogN) 까지도 가능할거라 생각한다. 여튼 3개의 용액을 골라야 하므로 N의 복잡도는 첫 시작 용액을 고르는 것에, 나머지 N은 투포인터 탐색으로 나머지 2개의 용액을 고르는 것에 사용하여 O(N^2)의 복잡도로 끝마무리 할 수 있다. 로직은 다음과 같다. 첫 번째 용액을 순서대로 선택한다. 고른 용액 이후의 용액들 중 2개의 용액을 투포인터 탐색을 통해 찾는다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #inclu..
2021.09.23

시뮬레이션 + 백트래킹 문제이다.

1차적으로 궁수 3명을 N+1 번째 행에 3명을 조합의 경우의 수로 세워둔다. 그 다음 2차적으로 시간을 N까지 증가시키면서 적들을 아래 칸으로 한칸씩 움직이도록 한다. 3차적으로 한 칸씩 움직인 적들 중 각 궁수에게 가장 가까운, 거리가 같다면 제일 왼쪽에 있는 놈을 찾는 O(NlogN) 로직을 짜준다. 그 후 하나하나 죽이면서 죽는 놈들을 세어주면 된다.

 

#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>

#define MAX_NUM 1000000009
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
int n, m, d;
int arr[17][17];
int check[16][16];
int dx[] = { -1,0,1,0 };
int dy[] = { 0,-1,0,1 };
vector<pii> am;
int maxn = 0;
pii arc_pos;
int cur_time;

bool compare(pii a, pii b) {
	int ta = abs(a.first + cur_time - arc_pos.first) + abs(a.second - arc_pos.second);
	int tb = abs(b.first + cur_time - arc_pos.first) + abs(b.second - arc_pos.second);
	if (ta == tb) {
		return a.second < b.second;
	}
	else {
		return ta < tb;
	}
}
int getAnmy(vector<pii> &arc) {
	int res = 0;
	int am_check[17][17] = { 0, };
	int checked[17][17] = { 0, };
	// 시간 [0, n)
	for (int t = 0; t < n; t++) {
		vector<pii> shoted;
		// 적 위치 -> 각 궁수들은 자신과 가장 가까운 놈을 찾아야함
		for (int j = 0; j < arc.size(); j++) {
			int ax = arc[j].first;
			int ay = arc[j].second;
			arc_pos = { ax, ay };
			cur_time = t;
			sort(am.begin(), am.end(), compare);

			for (auto pos : am) {
				int sx = pos.first;
				int sy = pos.second;
				if (sx + t > n) continue;
				if (abs(sx + t - ax) + abs(sy - ay) > d) break;
				if (checked[sx][sy]) continue;
				if (am_check[sx][sy] == 0)
					shoted.push_back({ sx, sy });
				am_check[sx][sy] = 1;
				break;
			}
		}

		for (int j = 0; j < shoted.size(); j++) {
			int tx = shoted[j].first;
			int ty = shoted[j].second;
			checked[tx][ty] = 1;
			res += 1;
		}
	}
	return res;
}
void bt(int num, int cnt, vector<pii> &arc) {
	int x = n+1, y = num;

	if (cnt == 3) {
		int res = getAnmy(arc);
		maxn = max(res, maxn);
		return;
	}
	if (num > m) return;

	arc.push_back({ x, y });
	bt(num + 1, cnt + 1, arc);
	arc.pop_back();
	bt(num + 1, cnt, arc);
}

int main() {
	scanf("%d %d %d", &n, &m, &d);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%d", &arr[i][j]);
			if (arr[i][j]) 
				am.push_back({ i,j });
		}
	}
	vector<pii> arc;
	bt(1, 0, arc);
	printf("%d\n", maxn);
	return 0;
}
 

17135번: 캐슬 디펜스

첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-23295] 스터디 시간 정하기 1  (0) 2021.11.05
[백준-1939] 중량제한  (0) 2021.10.21
[백준-3020] 개똥벌레  (0) 2021.10.01
[백준-14391] 종이조각  (0) 2021.10.01

해당 높이에 몇개의 장애물이 있는지 누적합을 사용하는 문제이다.

+-prefix 를 사용하여 어디서부터 어디까지 +인지 체크해주면 간단하게 누적합을 구할 수 있으며, O(N)의 복잡도로 문제를 풀 수 있다.

#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>
using namespace std;
typedef long long LL;

int sum[500001];
int main() {
	int n, m, a, b, c;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a);
		if (i % 2 == 0) {
			sum[m - a + 1] += 1;
		}
		else if (i % 2 != 0) {
			sum[a + 1] -= 1;
			sum[1] += 1;
		}
	}
	vector<int> ans = { 0 };
	for (int i = 1; i <= m; i++) {
		ans.push_back(ans.back() + sum[i]);
	}
	int minn = 200001;
	int mincnt = 0;
	for (int i = 1; i < ans.size(); i++) {
		if (minn > ans[i]) {
			mincnt = 1;
			minn = ans[i];
		}
		else if (minn == ans[i]) {
			mincnt += 1;
		}
	}
	printf("%d %d", minn, mincnt);
	return 0;
}
 

3020번: 개똥벌레

개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-1939] 중량제한  (0) 2021.10.21
[백준-17135] 캐슬디팬스  (0) 2021.10.03
[백준-14391] 종이조각  (0) 2021.10.01
[백준-19951] 태상이의훈련소생활  (0) 2021.09.30

백트래킹 문제이다. 일단 2차원 위치를 하나의 num으로 두고 나머지와, 몫으로 좌표를 설정하도록 한다. 그 후 하나씩 돌아가면서

  • 해당 수만 직사각형 종이에 포함할 것인가
  • 해당 수의 아래를 직사각형 종이에 포함할 것인가
  • 해당 수의 오른쪽을 직사각형 종이에 포함할 것인가

를 하나씩 처리해주면서 문제를 풀면 간단하다.

#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>

using namespace std;
// 입력값이 100만 -> nlogn 으로 끝내야 한다.

int arr[5][5];
int check[5][5];
int dx[] = { -1, 0 };
int dy[] = { 0, -1 };
int n, m;

int setCheck(int x, int y, int mode, int r, int num) {
	vector<int> ans;
	if (mode == 1) {
		for (int i = x; i <= x + r; i++) {
			if (check[i][y] && num == 1) return -1;
		}
		for (int i = x; i <= x + r; i++) {
			check[i][y] = num;
			ans.push_back(arr[i][y]);
		}
	}
	else {
		for (int i = y; i <= y + r; i++) {
			if(check[x][i] && num == 1) return -1;
		}
		for (int i = y; i <= y + r; i++) {
			check[x][i] = num;
			ans.push_back(arr[x][i]);
		}
	}
	int res = 0;
	for (int i = 0; i < ans.size(); i++) {
		res *= 10;
		res += ans[i];
	}
	return res;
}
int maxn = 0;

void bf(int num, int sum) {
	if (num > n * m) {
		maxn = max(sum, maxn);
		return;
	}
	int x, y;
	if (num % n == 0) {
		x = n;
		y = num / n;
	}
	else {
		x = num % n;
		y = num / n + 1;
	}
	
	if (check[x][y] == 1) {
		bf(num + 1, sum);
	}
	else if (check[x][y] == 0) {
		// 해당 원소만
		check[x][y] = 1;
		bf(num + 1, sum + arr[x][y]);
		check[x][y] = 0;

		// 아래 원소 포함
		for (int k = 1; k <= n - x; k++) {
			int tp = setCheck(x, y, 1, k, 1);
			if (tp == -1) continue;
			bf(num + 1, sum + tp);
			setCheck(x, y, 1, k, 0);
		}

		// 오른쪽 원소 포함
		for (int k = 1; k <= m - y; k++) {
			int tp = setCheck(x, y, 2, k, 1);
			if (tp == -1) continue;
			bf(num + 1, sum + tp);
			setCheck(x, y, 2, k, 0);
		}
	}
	maxn = max(sum, maxn);
}
int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf(" %1d", &arr[i][j]);
		}
	}
	bf(1, 0);
	printf("%d\n", maxn);
	return 0;
}

https://www.acmicpc.net/problem/14391

 

14391번: 종이 조각

영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고,

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-17135] 캐슬디팬스  (0) 2021.10.03
[백준-3020] 개똥벌레  (0) 2021.10.01
[백준-19951] 태상이의훈련소생활  (0) 2021.09.30
[백준-10800] 컬러볼  (0) 2021.09.30

+-누적합 문제이다.

값의 변경을 일일이 배열에 체킹해주면 터지게 된다. 때문에 이를 +-누적합을 통해 구해줄 수 있다.

  • ground : 첫 값이 들어가있는 배열
  • arr : "+ -" 체킹 배열
  • sum : 최종적으로 몇 만큼 변경해야하는지 들어있는 배열
#include <cstdio>

using namespace std;
typedef long long LL;

int sum[100001];
int arr[100002];
int ground[100002];

int main() {
	int n, m, a, b, c;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &ground[i]);
	}

	for (int i = 0; i < m; i++) {
		scanf("%d %d %d", &a, &b, &c);
		arr[a] += c;
		arr[b + 1] -= c;
	}

	for (int i = 1; i <= n; i++) 
		sum[i] = sum[i - 1] + arr[i];
	
	for (int i = 1; i <= n; i++) {
		ground[i] += sum[i];
		printf("%d ", ground[i]);
	}
	return 0;
}
 

19951번: 태상이의 훈련소 생활

2020년 5월 14일 논산훈련소에 입대한 태상이는 첫 총기 훈련에서 가스 조절기를 잃어버리는 중대한 실수를 범했다. 그로 인해, 태상이는 조교들에게 눈총을 받게 되었다. 조교들은 태상이에게 연

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-3020] 개똥벌레  (0) 2021.10.01
[백준-14391] 종이조각  (0) 2021.10.01
[백준-10800] 컬러볼  (0) 2021.09.30
[백준-10986] 나머지 합  (0) 2021.09.29

20만의 입력값에 대응하기 위해 nlogn 또는 n의 복잡도로 문제를 풀어야 한다.

이를 위해 누적합을 통해 문제를 풀 수 있다. 다만 전체 합에 대한 누적합과 각 색상에 대한 누적합을 따로 구하여 해당 값을 처리해주면 된다. 이를 2가지 방법으로 구현하였다.

  1. 각 색상에 대한 누적합을 구해놓고, 각각의 답을 구할 시에 이분탐색을 돌린다.
  2. 모든 명령어를 정렬한 뒤 색에 대한 누적합과 전체에 대한 누적합을 동시에 진행해준다.
#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
typedef long long LL;
typedef pair<int, int> pii;

LL input;
LL arr[2001];
LL all_sum[2001];
vector<vector<LL>> v(200001);
vector<vector<LL>> col_sum(200001);

// 입력값이 100만 -> nlogn 으로 끝내야 한다.
int main() {
	int n;
	scanf("%d", &n);

	LL a, b;
	queue<pii> q;
	
	for (int i = 0; i < n; i++) {
		scanf("%lld %lld", &a, &b);
		v[a].push_back(b);
		arr[b] += 1;
		q.push({ a,b });
	}
	
	// 전체 합 구하기
	for (LL i = 1; i <= 2000; i++) 
		all_sum[i] = i * arr[i] + all_sum[i - 1];

	// color 별 합 메모
	for (int i = 1; i <= n; i++) {
		if (v[i].empty()) continue;
		sort(v[i].begin(), v[i].end());
		for (int j = 0; j < v[i].size(); j++) {
			if (j == 0) {
				col_sum[i].push_back(v[i][j]);
				continue;
			}
			col_sum[i].push_back(col_sum[i].back() + v[i][j]);
		}
	}
	

	pii cur;
	while (!q.empty()) {
		cur = q.front();
		q.pop();
		LL sum = 0;
		int idx = lower_bound(v[cur.first].begin(), v[cur.first].end(), cur.second) - v[cur.first].begin();
		if (idx == 0) 
			sum = 0;
		else 
			sum = col_sum[cur.first][idx - 1];
		LL ans = all_sum[cur.second - 1] - sum;
		printf("%lld\n", (ans < 0) ? 0 : ans);
	}
	
	return 0;
}
#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>

using namespace std;
typedef long long LL;
typedef pair<int, int> pii;

LL input;
LL col_sum[200001];
LL size_sum[2001];

struct Ball {
	int idx;
	LL col, val;
	LL ret;
};

bool cmp(Ball &a, Ball &b) {
	if (a.val == b.val) {
		return a.col < b.col;
	}
	return a.val < b.val;
}
bool cmp1(Ball& a, Ball& b) {
	return a.idx < b.idx;
}
// 입력값이 100만 -> nlogn 으로 끝내야 한다.
int main() {
	int n, a, b;
	scanf("%d", &n);
	vector<Ball> all_arr(n);

	for (int i = 0; i < n; i++) {
		scanf("%lld %lld", &all_arr[i].col, &all_arr[i].val);
		all_arr[i].idx = i;
	}
	
	sort(all_arr.begin(), all_arr.end(), cmp);

	LL sum = 0;
	for (int i = 0; i < n; i++) {
		LL col = all_arr[i].col;
		LL val = all_arr[i].val;

		// 해당 색의 현재 누적합
		col_sum[col] += val;
		
		// 같은 크기의 누적합
		size_sum[val] += val;

		// 전체의 현재 누적합
		sum += val;

		all_arr[i].ret = sum - col_sum[col] - size_sum[val] + val;
		if (i != 0 && col == all_arr[i - 1].col && val == all_arr[i - 1].val) {
			all_arr[i].ret = all_arr[i - 1].ret;
		}
	}
	sort(all_arr.begin(), all_arr.end(), cmp1);

	for (int i = 0; i < n; i++) {
		printf("%lld\n", all_arr[i].ret);
	}

	return 0;
}
 

10800번: 컬러볼

첫 줄에는 공의 개수를 나타내는 자연수 N이 주어진다(1 ≤ N ≤ 200,000). 다음 N개의 줄 중 i번째 줄에는 i번째 공의 색을 나타내는 자연수 Ci와 그 크기를 나타내는 자연수 Si가 주어진다(1 ≤ Ci ≤ N

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-14391] 종이조각  (0) 2021.10.01
[백준-19951] 태상이의훈련소생활  (0) 2021.09.30
[백준-10986] 나머지 합  (0) 2021.09.29
[백준-11659]구간합구하기4  (0) 2021.09.29

누적합과 조합 계산식이 필요한 문제다.

일단 입력값을 보면 100만임을 봐서 최소 O(NlogN) 의 복잡도 내로 끝내야 함을 알 수 있다. 허나 이 문제의 경우 각 누적합을 통해 O(N) 복잡도로 끝낼 수 있다. 로직은 다음과 같다.

  • 입력되는 배열을 순서대로 sum 배열에 넣되 m으로 나눈 나머지 값을 쭉 넣어준다.
  • sum 배열을 순회하면서 원소를 pai 배열에 체킹해준다.
  • pai 배열에 체킹된 순서로 순회하면서 조합식을 더하면 답이 된다.

이렇게 pai 배열을 둔 이유는 sum[i] - sum[j] = 0 이 되는 경우의 수를 찾아야 하는데 결국 sum[i] == sum[j] 인 경우를 찾는 것과 다름이 없다. 따라서 같은 값을 가지는 sum 배열의 원소들을 쭉 체킹해준 다음 nC2의 조합식에 따라 단순 계산해주게 되면 답이 나오게 된다.

#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>
using namespace std;
typedef long long LL;

LL input;
LL sum[1000001];
LL pai[1001];
// 입력값이 100만 -> nlogn 으로 끝내야 한다.
int main() {
	int n;
	LL m;
	scanf("%d %lld", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &input);
		sum[i] = sum[i - 1] + (input % m);
		sum[i] %= m;
	}
	
	for (int i = 1; i <= n; i++) 
		pai[sum[i]] += 1;
	
	LL res = 0;
	for (LL i = 0; i < m; i++) {
		if (!pai[i]) continue;
		if (i == 0) {
			res += (pai[i] * (pai[i] - 1)) / 2;
			res += pai[i];
		}
		else {
			res += (pai[i] * (pai[i] - 1)) / 2;
		}
	}
	printf("%lld", res);
	return 0;
}
 

10986번: 나머지 합

수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오. 즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j)

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-19951] 태상이의훈련소생활  (0) 2021.09.30
[백준-10800] 컬러볼  (0) 2021.09.30
[백준-11659]구간합구하기4  (0) 2021.09.29
[백준-15724] 주지수  (0) 2021.09.28

 

구간합을 구하는 간단한 문제였다. 세그먼트 트리 누적합 으로 풀면 간단하게 풀린다. 누적합 로직은 다음과 같다.

  • (a~b)의 합 = b까지의 합 - (a-1)까지의 합

코드는 두가지 버전으로 작성해보았다.

// 세그먼트 트리 로직
#include <cstdio>

using namespace std;
typedef long long LL;
LL tree[300000];

LL query(int node, int s, int e, int l, int r) {
	if (e < l || r < s) return 0;
	if (l <= s && e <= r) return tree[node];
	else {
		return query(node * 2, s, (s + e) / 2, l, r) + 
			query(node * 2 + 1, (s + e) / 2 + 1, e, l, r);
	}
}
void update(int node, int s, int e, int idx, LL v) {
	if (idx < s || e < idx) return;
	if (s == e) tree[node] = v;
	else {
		update(2 * node, s, (s + e) / 2, idx, v);
		update(2 * node + 1, (s + e) / 2 + 1, e, idx, v);
		tree[node] = tree[node * 2] + tree[node * 2 + 1];
	}
}

int main() {
	int n, m, a, b;
	scanf("%d %d", &n, &m);
	LL input;
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &input);
		update(1, 1, n, i, input);
	}
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &a, &b);
		printf("%lld\n", query(1, 1, n, a, b));
	}
	return 0;
}

 

// 누적합으로 풀기
#include <cstdio>

using namespace std;
typedef long long LL;

int sum[100001];
int main() {
	int n, m, a, b;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a);
		sum[i] = sum[i - 1] + a;
	}
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &a, &b);
		printf("%d\n", sum[b] - sum[a - 1]);
	}
	return 0;
}
 

11659번: 구간 합 구하기 4

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-10800] 컬러볼  (0) 2021.09.30
[백준-10986] 나머지 합  (0) 2021.09.29
[백준-15724] 주지수  (0) 2021.09.28
[백준-2473] 세 용액  (0) 2021.09.23

카카오 6번 효율성 에 대해 검색하던 중 찾은 누적합 문제이다. 비슷하게 좌표를 통해 2차원 DP로 푸는 문제이다. 로직은 다음과 같다.

  • (i,j) 까지의 누적합 = (i,j)의 값 + (i-1,j)까지의 누적합 + (i,j-1)까지의 누적합 - (i-1,j-1) 까지의 누적합

 

#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>
#define MAX_NUM 1000000009
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
int arr[1300][1301];


int main() {
	int row, col, a;
	scanf("%d %d", &row, &col);
	for (int i = 1; i <= row; i++) {
		for (int j = 1; j <= col; j++) {
			scanf("%d", &a);
			arr[i][j] = a + arr[i - 1][j] + arr[i][j - 1] - arr[i - 1][j - 1];
		}
	}

	int n, x1, x2, y1, y2;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
		printf("%d\n", arr[x2][y2] - arr[x2][y1-1] - arr[x1-1][y2] + arr[x1-1][y1-1]);
	}
	return 0;
}

 

https://www.acmicpc.net/problem/15724

 

15724번: 주지수

네모 왕국의 왕인 진경대왕은 왕국의 영토를 편하게 통치하기 위해서 1X1의 단위 구역을 여러 개 묶어서 하나의 거대 행정구역인 주지수(州地數, 마을의 땅을 셈)를 만들 예정이다. 진경대왕은

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-10986] 나머지 합  (0) 2021.09.29
[백준-11659]구간합구하기4  (0) 2021.09.29
[백준-2473] 세 용액  (0) 2021.09.23
[백준-2467] 용액  (0) 2021.09.22

약간의 기술이 필요한 투 포인터 문제였다.

일단 기본적으로 5000의 입력값에 1초의 제한시간이기 때문에 O(N^2) 의 복잡도까지는 잘 통과할 것이다. O(N*NlogN) 까지도 가능할거라 생각한다.

여튼 3개의 용액을 골라야 하므로 N의 복잡도는 첫 시작 용액을 고르는 것에, 나머지 N은 투포인터 탐색으로 나머지 2개의 용액을 고르는 것에 사용하여 O(N^2)의 복잡도로 끝마무리 할 수 있다.

로직은 다음과 같다.

  • 첫 번째 용액을 순서대로 선택한다.
  • 고른 용액 이후의 용액들 중 2개의 용액을 투포인터 탐색을 통해 찾는다.
#define _CRT_SECURE_NO_WARNINGS

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string.h>
#include <math.h>

using namespace std;
typedef long long LL;

LL arr[5001];
int main() {
	LL n;
	scanf("%lld", &n);

	for (LL i = 0; i < n; i++) {
		scanf("%lld", &arr[i]);
	}
	sort(arr, arr + n);
	vector<LL> ans(3);
	LL minn = 21474836470, calc, mid;
	for (LL a = 0; a < n; a++) {
		mid = arr[a];
		for (LL lo = a + 1, hi = n - 1; lo < hi; ) {
			calc = arr[lo] + arr[hi] + arr[a];
			if (abs(calc) <= minn) {
				minn = abs(calc);
				ans[0] = arr[lo];
				ans[1] = arr[hi];
				ans[2] = mid;
			}
			if (calc < 0) {
				lo++;
			}
			else {
				hi--;
			}
		}
	}
	
	sort(ans.begin(), ans.end());
	printf("%lld %lld %lld\n", ans[0], ans[1], ans[2]);
	return 0;
}
 

2473번: 세 용액

첫째 줄에는 전체 용액의 수 N이 입력된다. N은 3 이상 5,000 이하의 정수이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상

www.acmicpc.net

 

'책장 > 알고리즘' 카테고리의 다른 글

[백준-11659]구간합구하기4  (0) 2021.09.29
[백준-15724] 주지수  (0) 2021.09.28
[백준-2467] 용액  (0) 2021.09.22
[백준-1949] 우수마을  (0) 2021.09.20