제출 #492712

#제출 시각아이디문제언어결과실행 시간메모리
492712Lam_lai_cuoc_doiAliens (IOI16_aliens)C++17
100 / 100
325 ms11500 KiB
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <class T>
void read(T &x)
{
    x = 0;
    register int c;
    while ((c = getchar()) && (c > '9' || c < '0'))
        ;
    for (; c >= '0' && c <= '9'; c = getchar())
        x = x * 10 + c - '0';
}

constexpr bool typetest = 0;

constexpr int N = 1e5 + 5;
constexpr ll Inf = 1e17;
int m, n, k;
pair<int, int> a[N];
ll cnt[N], sum[N];
int opt[N];

struct ConvexHullTrick
{
    vector<ll> A, B;
    vector<int> line;
    vector<ld> point;
    ConvexHullTrick(int n = 0)
    {
        A.resize(n + 2, 0);
        B.resize(n + 2, 0);
        point.emplace_back(-Inf);
    }

    ld ff(int x, int y)
    {
        return (ld)1.0 * (B[y] - B[x]) / (A[x] - A[y]);
    }

    void Add(int i)
    {
        while ((int)line.size() > 1 || ((int)line.size() == 1 && A[line.back()] == A[i]))
        {
            if (A[line.back()] == A[i])
            {
                if (B[line.back()] > B[i])
                {
                    line.pop_back();
                    if (!line.empty())
                        point.pop_back();
                }
                else
                    break;
            }
            else
            {
                if (ff(i, line.back()) <= ff(i, line[line.size() - 2]))
                {
                    line.pop_back();
                    if (!line.empty())
                        point.pop_back();
                }
                else
                    break;
            }
        }

        if (line.empty() || A[line.back()] != A[i])
        {
            if (!line.empty())
                point.emplace_back(ff(line.back(), i));
            line.emplace_back(i);
        }
    }

    ll More(int x)
    {
        return cnt[x - 1] * a[x].second + sum[x - 1];
    }

    pair<ll, int> Get(int x)
    {
        int j = lower_bound(point.begin(), point.end(), a[x].second) - point.begin();
        return {A[line[j - 1]] * a[x].second + B[line[j - 1]] + More(x), opt[line[j - 1]] + 1};
    }
};

pair<ll, ll> Cal(ll cost)
{
    ConvexHullTrick f(n);
    opt[0] = f.A[0] = 0;
    f.B[0] = cost;
    f.Add(0);

    for (int i = 1; i <= n; ++i)
    {
        pair<ll, int> v = f.Get(i);
        opt[i] = v.second;
        f.A[i] = -cnt[i];
        f.B[i] = v.first - sum[i] + cost;

        f.Add(i);

        if (i == n)
            return {v.second, v.first - v.second * cost};
    }
    return {0, 0};
}

long long take_photos(int N, int M, int K, vector<int> r, vector<int> c)
{
    /* Convert */
    m = M;
    n = N;
    k = K;
    for (int i = 1; i <= n; ++i)
    {
        a[i] = make_pair(r[i - 1] + 1, c[i - 1] + 1);
        if (a[i].first > a[i].second)
            swap(a[i].first, a[i].second);
    }

    sort(a + 1, a + n + 1, [&](const pair<int, int> &x, const pair<int, int> &y)
         { return x.second < y.second || (x.second == y.second && x.first > y.first); });

    vector<int> s;

    for (int i = 1; i <= n; ++i)
    {
        while (!s.empty() && a[i].first <= a[s.back()].first)
            s.pop_back();
        s.emplace_back(i);
    }

    n = s.size();
    k = min(k, n);

    for (int i = 1; i <= n; ++i)
        a[i] = a[s[i - 1]];

    /* End Convert */

    long long temp(0);

    for (int i = 1, j = 1, now = 0; i <= m; ++i)
    {
        if (j <= n && a[j].first == i)
        {
            now = a[j].second;
            ++j;
        }

        if (now >= i)
            temp += 2 * (now - i + 1) - 1;
    }

    for (int i = 1; i <= n; ++i)
    {
        if (i == n)
        {
            cnt[i] = (a[i].second - a[i].first + 1) * 2;
            sum[i] = -cnt[i] * a[i].second;
        }
        else if (a[i].second < a[i + 1].first)
        {
            cnt[i] = (a[i].second - a[i].first + 1) * 2;
            sum[i] = -cnt[i] * a[i].second;

            sum[i] += -1ll * (a[i + 1].first - a[i].second - 1) * (a[i + 1].first + a[i].second) + (a[i + 1].first - a[i].second - 1);
            cnt[i] += 2 * (a[i + 1].first - a[i].second - 1);
        }
        else
        {
            cnt[i] = (a[i + 1].first - a[i].first) * 2;
            sum[i] = -cnt[i] * a[i].second;
        }

        cnt[i] += cnt[i - 1];
        sum[i] += sum[i - 1];
    }

    ll ans(Inf);

    ll l = 1, mid, h = 1ll * m * m;

    while (l <= h)
    {
        mid = (l + h) / 2;
        if (Cal(mid).first >= k)
            l = mid + 1;
        else
            h = mid - 1;
    }

    // cout << h << '\n';

    pair<ll, ll> u = Cal(h);
    if (h == m * m)
        return u.second + temp;

    pair<ll, ll> v = Cal(l);

    if (v.first == u.first)
        return u.second + temp;

    ll a1 = k - u.first - k + v.first,
       b1 = (k - u.first) * (-v.second) + (k - v.first) * u.second;

    ans = -b1 / a1;

    return ans + temp;
}

void Read()
{
    int m, n, k;
    cin >> n >> m >> k;
    vector<int> x(n), y(n);
    for (int i = 0; i < n; ++i)
        cin >> x[i] >> y[i];

    cout << take_photos(n, m, k, x, y);
}

void Solve()
{
}

컴파일 시 표준 에러 (stderr) 메시지

aliens.cpp: In function 'void read(T&)':
aliens.cpp:12:18: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
   12 |     register int c;
      |                  ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...