본문 바로가기

PS(알고리즘 문제풀이) 관련 글/PS일지

2024-04-01

오늘은 만우절!

-수들의 합 2(2003, 백준)

 쉬운 2포인터 문제라고 생각했다. 시작점에 low, high를 잡아주고, m을 기준으로 투포인터를 돌리면 풀리는 간단한 문제이다. 풀고보니 O(N^2)도 돌아간다고 한다.

<소스 코드>

더보기
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n, m;
vector <int> vec;
int ans;

int main()
{
	int i, j;
	scanf("%d %d", &n, &m);
	for (i = 0; i < n; i++) {
		int x;
		scanf("%d", &x);
		vec.push_back(x);
	}vec.push_back(0);
	int low = 0, high = 0;
	int res = vec[0];
	while (low < n && high < n) {
		if (res == m) res += vec[++high], ans++;
		else if (res < m) res += vec[++high];
		else res -= vec[low++];
	}
	printf("%d", ans);
}

-화살표 그리기(15970, 백준)

 2018초등부 2번문제다. 색갈이 모두 다른 점들이 주어졌을 때 같은색중 가장 최소의 거리를 갖는 점과의 거리를 모두 더하는 문제이다. 각 색별로 따로 배열에 저장후 정렬해준다. 그 뒤, 순서대로 돌아가앞뒤 점중 가장 작은 점과의 거리를 ans에 더하면 된다.

<소스 코드>

더보기
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n;
vector<int> vec[5010];

int main()
{
	int i, j;
	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		vec[y].push_back(x);
	}
	for (i = 1; i <= n; i++) {
		if (vec[i].size() == 0) continue;
		else sort(vec[i].begin(), vec[i].end());
	}
	int ans = 0;
	for (i = 1; i <= n; i++) {
		if (vec[i].size() == 0) continue;
		for (j = 0; j < vec[i].size(); j++) {
			int res = 2e9;
			if (j > 0 && res > vec[i][j] - vec[i][j - 1]) res = vec[i][j] - vec[i][j - 1];
			if (j < vec[i].size() - 1 && vec[i][j + 1] - vec[i][j] < res) res = vec[i][j + 1] - vec[i][j];
			ans += res;
		}
	}
	printf("%d", ans);
	return 0;
}

-수 고르기(2230, 백준)

 쉬운 2포인터 문제다. 마찬가지로 시작점에 low와 high를 잡은뒤, m을 기준으로 차의 투포인터를 돌려주면 쉽게 풀린다.

<소스 코드>

더보기
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n, m;
vector <int> vec;

int main() 
{
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++) {
		int x;
		scanf("%d", &x);
		vec.push_back(x);
	}
	int ans = 2e9;
	sort(vec.begin(), vec.end());
	int low = 0, high = 0;
	while (low < n && high < n) {
		int res = vec[high] - vec[low];
		if (res < m) {
			high++;
		}
		else {
			ans = min(ans, res);
			low++;
		}
	}
	printf("%d", ans);
	return 0;
}

-XCorr(15976, 백준)

 아이디어가 생각보다 쉽게 떠올랐다. 문제에서 주어지지않은 배열의 idx값은 0임으로, 서로의 채워진 배열끼리 만나는 경우를 구하면 된다. 즉 문제에서 주어진 a, b범위내에서 만나는 배열의 값끼리만 곱해서 더해주면 된다. 이때 a, b범위내에 있는 배열은 연속함으로, 누적합을 이용해 한번에 구할 수 있다. 배열의 범위값을 찾는데는 2분탐색 lower bound를 이용했다.

y배열의 누적합 구하기 -> x좌표 탐색해가면서 현재 idx + a와 idx + b에 가까운 수를 y의 idx배열에서 찾기(lower_bound) -> 범위 내의 누적합 * 현재 x배열의 값을 ans에 더해주기 -> ans 출력

lower_bound에서 +m을 해야되는데 +n을 해놓고 1시간동안 못찾아서 시간 증발 ㅠ.ㅠ

<소스 코드>

더보기
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

long long n, m;
long long vx_idx[300010], vx_val[300010];
long long vy_idx[300010], vy_val[300010], sumy[300010];
long long a, b;

int main()
{
	long long i, j;
	scanf("%lld", &n);
	for (i = 1; i <= n; i++) scanf("%lld %lld", &vx_idx[i], &vx_val[i]);
	scanf("%lld", &m);
	for (i = 1; i <= m; i++) scanf("%lld %lld", &vy_idx[i], &vy_val[i]);
	for (i = 1; i <= m; i++) sumy[i] = sumy[i - 1] + vy_val[i];
	scanf("%lld %lld", &a, &b);
	long long ans = 0;
	for (i = 1; i <= n; i++) {
		long long idx = vx_idx[i], val = vx_val[i];
		long long low = lower_bound(vy_idx + 1, vy_idx + m + 1, idx + a) - (vy_idx);
		long long high = lower_bound(vy_idx + 1, vy_idx + m + 1, idx + b) - (vy_idx);
		if (high > m) high--;
		if (vy_idx[high] > idx + b) high--;
		ans += val * (sumy[high] - sumy[low - 1]);
	}
	printf("%lld", ans);
	return 0;
}

'PS(알고리즘 문제풀이) 관련 글 > PS일지' 카테고리의 다른 글

2024-04-18  (1) 2024.04.18
2024-03-31  (0) 2024.03.31
2024-03-29  (2) 2024.03.29
2024-03-27  (2) 2024.03.27
2024-03-23  (1) 2024.03.23