2 minute read

문제접근

예제에서 살펴볼 수 있듯이 1 2 4가 주어졌을때

3,3,2,3,2,1,0

이렇게 순차적으로 줄어드는 값이라는걸 알 수 있다. 오름차순으로 주어지긴때문에 각 구간의 차이를 (날짜)

arr[i] - arr[i - 1]

이렇게 나타낼 수 있다. 그렇다면 날짜의 차이를 이용하여 코인의 가격을 보면

ll fac(ll now, ll next,ll z)
{
    ll sum = 0;
    ll st = abs(next - now);
    for (int i = 0; i < st; i++)
    {
        sum += z;
        if (z == 0)
            break;
        
    }
    return sum;
}

하지만 이렇게 하면 시간초과가 난다. 그래서 1부터 n까지의 합을 구하는 수학식을 사용한다.

1부터 n까지의 합 식: (n * (n + 1)) / 2 10일때 10 * 11 / 2 이므로 55가 나오게 된다.

그렇다면 10의 값이 코인가격으로 주워졌을때 1일에서 5일까지는 10 9 8 7이므로 34가 될것이다. 이를 수학식으로 나타내면

(10 * (5 - 1) - ((5 - 1) * ((5 - 1) - 1) / 2))

계산해보면 40 - ((4 * 3) / 2) 이므로 34가 나오게 된다.
이렇게 n부터 n - a까지의 합을 구할 수 있다.
이를 이용하여 시간초과가 나지 않게 풀 수 있다.

코드

#include <bits/stdc++.h> 
#define ll long long

using namespace std;

ll cal(ll w, ll mid)
{
	ll sum = (mid * w) - (w * (w - 1) / 2);
	return sum;
}

ll sol(const vector<ll>& x,ll mid)
{
	ll sum = 0;
	int size = x.size();
	for (int i = 1; i < size; i++)
	{
		sum += cal(min(x[i] - x[i - 1], mid), mid);
	}
	sum += cal(mid, mid);
	return sum;
}

ll ebun(const vector<ll>& x, ll k)
{
	ll lo = 1;
	ll hi = 1500000000; //구간설정 주의
	while (lo <= hi)
	{
		ll mid = (lo + hi) / 2;
		if (sol(x, mid) < k)
		{
			lo = mid + 1;
		}
		else
		{
			hi = mid - 1;
		}
	}
	return lo;
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);
	int n;
	ll k;
	cin >> n >> k;
	vector<ll> v(n);
	for (int i = 0; i < n; i++)
		cin >> v[i];
	cout << ebun(v, k);
}

시간초과 코드

#include <bits/stdc++.h> 
#define ll long long

using namespace std;

ll fac(ll now, ll next,ll z)
{
    ll sum = 0;
    ll st = abs(next - now);
    for (int i = 0; i < st; i++) //이부분에서 시간초과가 난다
    {
        sum += z; 
        if (z == 0)
            break;
        
    }
    return sum;
}

ll cal(const vector<ll>& x,ll mid)
{
    ll sum = 0;
    int size = x.size();
    for (int i = 1; i < size; i++)
    {
        sum += fac(x[i - 1], x[i],mid);
    }
    sum += fac(x[size - 1], 0, mid);
    return sum;
}

ll ebun(const vector<ll>& x, ll k)
{
    ll lo = 1;
    ll hi = k;
    while (lo <= hi)
    {
        ll mid = (lo + hi) / 2;
        if (cal(x, mid) < k)
        {
            lo = mid + 1;
        }
        else
        {
            hi = mid - 1;
        }
    }
    return lo;
}

int main()
{
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    int n;
    ll k;
    cin >> n >> k;
    vector<ll> v(n);
    for (int i = 0; i < n; i++)
        cin >> v[i];
    cout << ebun(v, k);
}

Leave a comment