문제 읽으면서 어?? 디피?? 최소면 디피인가?? 생각이 들었는데 DP는 아닌 것 같고..
약간 부분합 느낌이 들긴 했는데 부분합을 어떻게 써야 할지 몰랐다.
문제를 어떻게 해결해야 할지는 감을 잡았다.
손익분기점처럼 a*k와 b*k + c 중 최소를 찾으면 되는데 문제는 k, 도로를 지나는 횟수를 구하는 게 문제였다.
1 4라면 1, 2, 3번 도로의 횟수를 1 증가하면 되는데 이걸 배열에 각각 접근하게 되면 n^2이 걸려 시간초과가 나게 된다ㅜㅜ
북님한테 힌트 받아서 풀었다. 알고보니 전에 풀었던 개념을 응용하면 됐었다!
https://burningjeong.tistory.com/286
작업일지 문제를 응용해서 풀었다. (역시 교육적인 문제였다)
3에서 6까지 값을 계산하려면 부분합 배열의 3번째에 +1을 6=7번째에 -1을 하고 마지막에 부분합 해주면 된다.
쩔어~~
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cmath>
#define xx first
#define yy second
#define all(x) (x).begin(), (x).end()
using namespace std;
using i64 = long long;
using ii = pair<int, int>;
using ii64 = pair<i64, i64>;
int stack_[200005];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
vector<int> p(m);
for (int i = 0; i < m; i++)
scanf("%d", &p[i]);
vector<i64> sum(n + 5);
for (int i = 0; i < m - 1; i++)
{
if (p[i] < p[i + 1])
{
sum[p[i]] += 1;
sum[p[i + 1]] += -1;
}
else
{
sum[p[i + 1]] += 1;
sum[p[i]] += -1;
}
}
for (int i = 1; i <= n; i++)
sum[i] = sum[i] + sum[i - 1];
i64 ans = 0;
for (int i = 1; i < n; i++)
{
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
if (sum[i] != 0)
ans += min(a*sum[i], b*sum[i] + c);
}
printf("%lld\n", ans);
return 0;
}
'백준' 카테고리의 다른 글
1064 평행사변형 (0) | 2020.08.31 |
---|---|
1493 박스 채우기 (0) | 2020.08.30 |
15805 트리 나라 관광 가이드 (0) | 2020.08.26 |
3187 양치기 꿍 (0) | 2020.08.25 |
2435 기상청 인턴 신현수 (0) | 2020.08.25 |