제출 #921980

#제출 시각아이디문제언어결과실행 시간메모리
921980boris_mihovCake 3 (JOI19_cake3)C++17
100 / 100
1271 ms18672 KiB
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cassert>
#include <vector>
#include <queue>

typedef long long llong;
const int MAXN = 200000 + 10;
const llong INF = 1e18;

int n, k;
int v[MAXN];
int c[MAXN];
int sortedV[MAXN];
struct SegmentTree
{
    struct Node
    {
        llong sum;
        int cnt;

        Node()
        {
            sum = cnt = 0;
        }

        friend Node operator + (const Node &left, const Node &right)
        {
            Node res;
            res.sum = left.sum + right.sum;
            res.cnt = left.cnt + right.cnt;
            return res;
        }
    };

    Node tree[4*MAXN];
    void update(int l, int r, int node, int queryPos)
    {
        if (l == r)
        {
            if (tree[node].cnt == 1)
            {
                tree[node].sum = 0;
                tree[node].cnt = 0;
            } else
            {
                tree[node].sum = sortedV[l];
                tree[node].cnt = 1;
            }

            return;
        }

        int mid = (l + r) / 2;
        if (queryPos <= mid) update(l, mid, 2*node, queryPos);
        else update(mid + 1, r, 2*node + 1, queryPos);
        tree[node] = tree[2*node] + tree[2*node + 1];
    }

    int findPos(int l, int r, int node, int k)
    {
        if (l == r)
        {
            return l;
        }

        int mid = (l + r) / 2;
        if (tree[2*node].cnt >= k)
        {
            return findPos(l, mid, 2*node, k);
        } else
        {
            return findPos(mid + 1, r, 2*node + 1, k - tree[2*node].cnt);
        }
    }

    llong query(int l, int r, int node, int queryL, int queryR)
    {
        if (queryL <= l && r <= queryR)
        {
            return tree[node].sum;
        }

        llong res = 0;
        int mid = (l + r) / 2;
        if (queryL <= mid) res += query(l, mid, 2*node, queryL, queryR);
        if (mid + 1 <= queryR) res += query(mid + 1, r, 2*node + 1, queryL, queryR);
        return res;
    }

    void update(int pos)
    {
        update(1, n, 1, pos);
    }

    llong query()
    {
        int to = findPos(1, n, 1, k);
        return query(1, n, 1, 1, to);
    }
};

int inOrder[MAXN];
int revOrder[MAXN];
std::pair <int,int> toSort[MAXN];
SegmentTree tree;

int ptrL = 1;
int ptrR = 0;
llong cost(int l, int r)
{
    r--;
    l++;
    while (ptrL < l)
    {
        tree.update(revOrder[ptrL]);
        ptrL++;
    }

    while (ptrL > l)
    {
        ptrL--;
        tree.update(revOrder[ptrL]);
    }

    while (ptrR > r)
    {
        tree.update(revOrder[ptrR]);
        ptrR--;
    }

    while (ptrR < r)
    {
        ptrR++;
        tree.update(revOrder[ptrR]);
    }

    return tree.query() + v[l - 1] + v[r + 1] - 2 * (c[r + 1] - c[l - 1]);
}

llong ans = -INF;
void divide(int l, int r, int optL, int optR)
{
    int opt = -1;
    llong curr = -INF;
    int mid = (l + r) / 2;

    for (int i = std::max(mid + k + 1, optL) ; i <= optR ; ++i)
    {
        llong res = cost(mid, i);
        if (res > curr)
        {
            curr = res;
            opt = i;
        }
    }

    ans = std::max(ans, curr);
    if (l < mid) divide(l, mid - 1, optL, opt);
    if (mid < r) divide(mid + 1, r, opt, optR);
}

void solve()
{
    std::sort(toSort + 1, toSort + 1 + n);
    for (int i = 1 ; i <= n ; ++i)
    {
        c[i] = toSort[i].first;
        v[i] = toSort[i].second;
    }

    std::iota(inOrder + 1, inOrder + 1 + n, 1);
    std::sort(inOrder + 1, inOrder + 1 + n, [&](int x, int y)
    {
        return v[x] > v[y];
    }); 

    for (int i = 1 ; i <= n ; ++i)
    {
        sortedV[i] = v[inOrder[i]];
        revOrder[inOrder[i]] = i;
    }

    k -= 2;
    divide(1, n - k - 1, 1, n);
    std::cout << ans << '\n';
}

void input()
{
    std::cin >> n >> k;
    for (int i = 1 ; i <= n ; ++i)
    {
        std::cin >> toSort[i].second >> toSort[i].first;
    }
}   

void fastIOI()
{
    std::ios_base :: sync_with_stdio(0);
    std::cout.tie(nullptr);
    std::cin.tie(nullptr);
}

int main()
{
    fastIOI();
    input();
    solve();

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...