답안 #443948

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
443948 2021-07-12T14:57:49 Z blue Candies (JOI18_candies) C++17
0 / 100
3 ms 1996 KB
#include <iostream>
#include <vector>
#include <set>
using namespace std;

const int maxN = 200000;

int N;
long long A[2+maxN];
long long* Asum = new long long[2+maxN];

long long INF = 1'000'000'000'000'000'000LL;

struct block
{
    int i;
    int j;

    long long score()
    {
        return Asum[j] - Asum[i - 2];
    }

    long long expand_score()
    {
        if(j == N || i == 1) return -INF;
        else return Asum[j+1] - Asum[i-1 - 2];
    }

    long long gain()
    {
        return expand_score() - score();
    }
};

bool operator < (block X, block Y)
{
    if(X.gain() == Y.gain())
    {
        return X.i < Y.i;
    }
    return X.gain() > Y.gain();
}



struct new_block
{
    int i;
};

bool operator < (new_block X, new_block Y)
{
    if(A[X.i] == A[Y.i]) return X.i < Y.i;
    return A[X.i] > A[Y.i];
}



set<block> B;
set<new_block> NB;

vector<int> start_block(1+maxN, 0); //end_block of block start_blocking at i
vector<int> end_block(1+maxN, 0); //start_block of block end_blocking at i


void combine_blocks(int i)
{
    if(i < 1 || N < i) return;
    if(start_block[i] == 0 || end_block[i+2] == 0) return;

    int a = start_block[i];
    int b = end_block[i+2];

    block X = block{a, i};
    block Y = block{i+2, b};

    B.erase(X);
    B.erase(Y);

    start_block[i] = end_block[i] = start_block[i+2] = end_block[i+2] = 0;
    end_block[a] = b;
    start_block[b] = a;

    B.insert(block{a, b});
}

int main()
{
    A[0] = A[N+1] = 0;

    cin >> N;
    for(int i = 1; i <= N; i++) cin >> A[i];

    Asum = &Asum[1];
    Asum[-1] = Asum[0] = 0;
    for(int i = 1; i <= N; i++) Asum[i] = Asum[i-2] + A[i];

    for(int i = 1; i <= N; i++)
    {
        NB.insert(new_block{i});
    }

    long long ans = 0;

    for(int j = 1; j <= N/2 + N%2; j++)
    {
        // cerr << "\n\n\n\n\nj = " << j << '\n';
        // cerr << "B.size() == " << B.size() << ", NB.size() == " << NB.size() << '\n';
        // block b0 = *B.begin();
        if(B.size() == 0 || (NB.size() > 0 && A[NB.begin()->i] > block{B.begin()->i, B.begin()->j}.gain()))
        {
            // cerr << "case 1\n";
            /*
            1. Build the new block.
            2. Get rid of all (new blocks) in [i-1, i+1].
            3. See if this can be combined with a block to the left
            4. See if this can be combined with a block to the right.
            */

            int I = NB.begin()->i;
            NB.erase(NB.begin());

            // cerr << "hello\n";

            B.insert(block{I, I});
            start_block[I] = end_block[I] = I;

            // cerr << "check\n";

            if(I-1 >= 1)
                NB.erase(new_block{I-1});

            if(I+1 <= N)
                NB.erase(new_block{I+1});

            ans += A[I];

            if(I-2 >= 1)
                combine_blocks(I-2);

            if(I+2 <= N)
                combine_blocks(I);

            // cerr << "done\n";
        }
        else
        {
            int I = B.begin()->i;
            int J = B.begin()->j;
            B.erase(B.begin());

            ans += block{I, J}.gain();

            B.insert(block{I-1, J+1});

            if(I-2 >= 1)
                NB.erase(new_block{I-2});
            if(J+2 <= N)
                NB.erase(new_block{J+2});

            combine_blocks(I-1 - 2);
            combine_blocks(J+1);
        }

        cout << ans << '\n';
    }
}
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 1996 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 1996 KB Output isn't correct
2 Halted 0 ms 0 KB -