제출 #808897

#제출 시각아이디문제언어결과실행 시간메모리
808897htphong0909휴가 (IOI14_holiday)C++17
100 / 100
1328 ms5816 KiB
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
using namespace std;

set<pair<int, int>> selected;
set<pair<int, int>, greater<>> notSelected;
long long curValue = 0;
int lt = 1;
int rt = 0;
int n, d, start;
int cnt;
int arr[100001];
long long ans = -1e18;

void trade()
{
    pair<int, int> temp1 = *notSelected.begin();
    pair<int, int> temp2 = *selected.begin();
    curValue = curValue - temp2.first + temp1.first;
    notSelected.erase(temp1);
    notSelected.insert(temp2);
    selected.erase(temp2);
    selected.insert(temp1);
}

void unselect()
{
    cnt++;
    pair <int, int> temp = *selected.begin();
    notSelected.insert(temp);
    curValue -= temp.first;
    selected.erase(temp);
}

void select()
{
    cnt--;
    pair <int, int> temp = *notSelected.begin();
    selected.insert(temp);
    curValue += temp.first;
    notSelected.erase(temp);
}

void Add(int x)
{
    notSelected.insert(make_pair(arr[x], x));
}

void Del(int x)
{
    if (selected.find(make_pair(arr[x], x)) != selected.end())
    {
        selected.erase(make_pair(arr[x], x));
        curValue -= arr[x];
        cnt++;
        if (!notSelected.empty() && cnt > 0) select();
    }
    else notSelected.erase(make_pair(arr[x], x));
}

int calcDis(int l, int r)
{
    if (l > r) return 0;
    if (start <= l) return(l - start + (r - l));
    if (start >= r) return(start - r + (r - l));
    return (min(start - l, r - start) + (r - l));
}

long long cost(int l, int r)
{
    while (lt != l || rt != r)
    {
        while (rt < r)
        {
            cnt += calcDis(lt, rt) - calcDis(lt, rt + 1);
            rt++;
            Add(rt);
            while (!notSelected.empty() && !selected.empty() && notSelected.begin()->first > (selected.begin())->first) trade();
            while (cnt < 0 && !selected.empty()) unselect();
            while (cnt > 0 && !notSelected.empty()) select();
        }
        while (rt > lt && rt > r)
        {
            cnt += calcDis(lt, rt) - calcDis(lt, rt - 1);
            Del(rt);
            rt--;
            while (!notSelected.empty() && !selected.empty() && notSelected.begin()->first > (selected.begin())->first) trade();
            while (cnt < 0 && !selected.empty()) unselect();
            while (cnt > 0 && !notSelected.empty()) select();
        }
        while (lt < rt && lt < l)
        {
            cnt += calcDis(lt, rt) - calcDis(lt + 1, rt);
            Del(lt);
            lt++;
            while (!notSelected.empty() && !selected.empty() && notSelected.begin()->first > (selected.begin())->first) trade();
            while (cnt < 0 && !selected.empty()) unselect();
            while (cnt > 0 && !notSelected.empty()) select();
        }
        while (lt > l)
        {
            cnt += calcDis(lt, rt) - calcDis(lt - 1, rt);
            lt--;
            Add(lt);
            while (!notSelected.empty() && !selected.empty() && notSelected.begin()->first > (selected.begin())->first) trade();
            while (cnt < 0 && !selected.empty()) unselect();
            while (cnt > 0 && !notSelected.empty()) select();
        }
    }
    return curValue;
}

void divide(int l, int r, int gL, int gR)
{
    if (l > r) return;
    int mid = (l + r) / 2;
    long long bestCost = -1e18;
    int bestPos = gL;
    for (int i = gL; i <= min(mid, gR); i++)
    {
        if (cost(i, mid) > bestCost)
        {
            bestCost = cost(i, mid);
            bestPos = i;
        }
    }
    ans = max(ans, bestCost);
    divide(l, mid - 1, gL, bestPos);
    divide(mid + 1, r, bestPos, gR);
}

long long findMaxAttraction(int _n, int _start, int _d, int *attraction)
{
    n = _n;
    d = _d;
    start = _start + 1;
    for (int i = 1; i <= n; i++) arr[i] = attraction[i - 1];
    cnt = d;
    divide(1, n, 1, n);
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...