Submission #622825

#TimeUsernameProblemLanguageResultExecution timeMemory
622825AlexandruabcdeAliens (IOI16_aliens)C++14
0 / 100
1 ms336 KiB
#include "aliens.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
constexpr int NMAX = 1e6 + 5;

struct Interval {
    int st, dr;

    bool operator < (const Interval &other) const {
        return (st < other.st || (st == other.st && dr > other.dr));
    }
};

int N, M, K;
Interval V[NMAX];

LL Cost (int a, int b) {
    return 1LL * (b-a+1) * (b-a+1);
}

void Comprim () {
    sort(V+1, V+N+1);

    vector <Interval> aux;

    for (int i = 1; i <= N; ++ i ) {
        if (aux.empty()) {
            aux.push_back(V[i]);
            continue;
        }

        if (aux.back().dr < V[i].dr)
            aux.push_back(V[i]);
    }

    N = aux.size();

    for (int i = 1; i <= N; ++ i )
        V[i] = aux[i-1];
}

/*
LL dp[4005][4005];

void Solve_Dp_Brut () {
    for (int j = 1; j <= K; ++ j ) {
        for (int i = 1; i <= N; ++ i ) {
            dp[i][j] = Cost(V[1].st, V[i].dr);

            if (j == 1) continue;

            dp[i][j] = min(dp[i][j], dp[i-1][j-1] + Cost(V[i].st, V[i].dr));

            for (int c = i-1; c >= 1; -- c ) {
                int p = V[c+1].st;
                int new_capat = V[c].dr;

                dp[i][j] = min(dp[i][j], dp[c][j-1] + Cost(p, V[i].dr) - (p <= new_capat ? Cost(p, new_capat) : 0));
            }
        }
    }
}
*/

/*

[dp[c][j-1] - (p <= new_capat ? Cost(p, new_capat) : 0)] + (V[i].dr - p + 1)^2


V[i].dr ^ 2   -   2 * V[i].dr * (p-1) + (p - 1) ^ 2


*/
pair <LL, int> dp[NMAX];
deque <int> D;

pair <LL, LL> Equation (int ind) {
    pair <LL, LL> ans;

    int p = V[ind+1].st;
    int new_capat = V[ind].dr;
    ans.second = dp[ind].first - (p <= new_capat ? Cost(p, new_capat) : 0) + 1LL * (p - 1) * (p - 1);
    ans.first = - 2 * (p-1);

    return ans;
}

long double Intersect (int i, int j) {
    pair <LL, LL> pr = Equation(i);
    pair <LL, LL> sec = Equation(j);

    return 1.0 * (pr.second - sec.second) / (sec.first - pr.first);
}

pair <LL, int> Check (LL penalty) {
    dp[0] = {0, 0};
    D.clear();
    for (int i = 1; i <= N; ++ i ) {
        dp[i] = {Cost(V[1].st, V[i].dr) + penalty, 1};

        dp[i] = min(dp[i], {dp[i-1].first + Cost(V[i].st, V[i].dr) + penalty, dp[i-1].second + 1});

        while (D.size() > 2 && Intersect(D[0], D[1]) < 1.0 * V[i].dr)
            D.pop_front();

        if (!D.empty()) {
            pair <LL, LL> ec = Equation(D.front());
            dp[i] = min(dp[i], {ec.first * V[i].dr + ec.second + penalty + 1LL * V[i].dr * V[i].dr, dp[D.front()].second + 1});
        }

        if (i == N) break;

        while (D.size() > 2 && Intersect(i, D.back()) < Intersect(D.back(), D[D.size()-2]))
            D.pop_back();

        D.push_back(i);
    }

    return dp[N];
}

LL Solve_Optim () {
    LL st = 0, dr = 1e12;

    while (st <= dr) {
        LL mij = (st + dr) >> 1;

        pair <LL, int> pos = Check(mij);

        if (pos.second == K)
            return (pos.first - 1LL * K * mij);

        if (pos.second < K) {
            dr = mij - 1;
        }
        else st = mij + 1;
    }

    pair <LL, int> pos = Check(st);

    return (pos.first - 1LL * K * st);
}

long long take_photos(int n, int m, int k, std::vector<int> r, std::vector<int> c) {
    N = n;
    M = m;
    K = k;

    for (int i = 1; i <= N; ++ i ) {
        V[i].st = min(r[i-1], c[i-1]);
        V[i].dr = max(r[i-1], c[i-1]);
    }

    Comprim();
    ///Solve_Dp();

    ///return dp[N][K];

    return Solve_Optim();
}
#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...