Submission #432275

#TimeUsernameProblemLanguageResultExecution timeMemory
432275blueRoad Construction (JOI21_road_construction)C++17
11 / 100
10051 ms59524 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;

/*
We transform each point (x, y) into a point (x', y') where x' = x+y and y' = x-y. The Manhattan
distance between (x1, y1) and (x2, y2) = |x1-x2| + |y1-y2| = max( |x1'-x2'|, |y1'-y2'| ).

1. Transform each point (x, y) into a point (x1, y1) where x1 = x+y and y1 = x-y. √
2. Sort the points (x1, y1) twice, once by x1 and once by y1. √
3. Iterate over points sorted by x1:
4.      Maintain a set of these points sorted by the distance to the closest neighbor.
5.      Repeatedly, find the smallest such distance.
6.      If this distance is larger than the X-Y distance, add it to the result set.
*/

long long long_absval(long long x)
{
    return max(x, -x);
}

const int maxN = 250000;
const long long INF = 1'000'000'000'000'000'000LL;

vector<long long> A(1+maxN), B(1+maxN);
vector<int> I_A, I_B;

int N, K;

struct loc
{
    int i;
    long long v;
};

bool operator < (loc P, loc Q)
{
    if(P.v == Q.v) return P.i < Q.i;
    return P.v < Q.v;
}


vector<int> nxtA, nxtB;
vector<long long> valA, valB;

void compute_score_A(int i)
{
    valA[i] = INF;
    if(nxtA[i] <= N-1)
    {
        valA[i] = A[ I_A[nxtA[i]] ] - A[ I_A[i] ];
    }
}

void compute_score_B(int i)
{
    valB[i] = INF;

    if(nxtB[i] <= N-1)
    {
        valB[i] = B[ I_B[nxtB[i]] ] - B[ I_B[i] ];
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> N >> K;

    for(int i = 1; i <= N; i++)
    {
        long long X, Y;
        cin >> X >> Y;
        A[i] = X+Y;
        B[i] = X-Y;
    }

    I_A = I_B = vector<int>(N);
    for(int i = 0; i < N; i++)
    {
        I_A[i] = i+1;
        I_B[i] = i+1;
    }

    sort(I_A.begin(), I_A.end(), [] (int p, int q)
    {
        return A[p] < A[q];
    });

    sort(I_B.begin(), I_B.end(), [] (int p, int q)
    {
        return B[p] < B[q];
    });

    multiset<long long> res;







    nxtA = vector<int>(N);
    for(int i = 0; i < N; i++)
    {
        nxtA[i] = i+1;
    }

    valA = vector<long long>(N, INF);
    for(int i = 0; i < N; i++)
    {
        compute_score_A(i);
    }
    set<loc> LA;
    for(int i = 0; i < N; i++) LA.insert(loc{i, valA[i]});









    nxtB = vector<int>(N);
    for(int i = 0; i < N; i++)
    {
        nxtB[i] = i+1;
    }

    valB = vector<long long>(N, INF);
    for(int i = 0; i < N; i++)
    {
        compute_score_B(i);
    }

    set<loc> LB;
    for(int i = 0; i < N; i++) LB.insert(loc{i, valB[i]});






    while(res.size() < K)
    {
        if(valA[LA.begin()->i] < valB[LB.begin()->i])
        {
            int i = LA.begin()->i;

            LA.erase(LA.begin());

            // cerr << i << ' ' << val[i] << ' ' << nxt[i] << '\n';

            // if(val[i] >= INF) break;

            int j = nxtA[i];               //!!!!!

            if(j > N-1) break;

            if(long_absval(A[ I_A[i] ] - A[ I_A[j] ]) >= long_absval(B[ I_A[i] ] - B[ I_A[j] ]))
            {
                res.insert(long_absval(A[ I_A[i] ] - A[ I_A[j] ]));
                // cerr << I_A[i] << ' ' << I_A[j] << ' ' << abs(A[ I_A[i] ] - A[ I_A[j] ]) << '\n';
            }
            nxtA[i]++;
            compute_score_A(i);

            LA.insert(loc{i, valA[i]});
        }
        else
        {
            int i = LB.begin()->i;

            LB.erase(LB.begin());

            int j = nxtB[i];               //!!!!!

            // cerr << i << ' ' << val[i] << ' ' << nxt[i] << '\n';

            if(j > N-1) break;

            if(long_absval(B[ I_B[i] ] - B[ I_B[j] ]) > long_absval(A[ I_B[i] ] - A[ I_B[j] ]))
            {
                res.insert(long_absval(B[ I_B[i] ] - B[ I_B[j] ]));
                // cerr << I_B[i] << ' ' << I_B[j] << ' ' << abs(B[ I_B[i] ] - B[ I_B[j] ]) << '\n';
            }
            nxtB[i]++;
            compute_score_B(i);

            LB.insert(loc{i, valB[i]});
        }
    }







    int ct = 0;
    for(long long r:res)
    {
        ct++;
        if(ct > K) break;
        cout << r << '\n';
    }
}

/* Version 1


//Part 1: iterate over I_A;
nxtA = vector<int>(N);
for(int i = 0; i < N; i++)
{
    nxtA[i] = i+1;
}

valA = vector<long long>(N, INF);
for(int i = 0; i < N; i++)
{
    compute_score_A(i);
}

set<loc> LA;
for(int i = 0; i < N; i++) LA.insert(loc{i, valA[i]});

++++

while(res.size() < K)
{
    int i = LA.begin()->i;

    LA.erase(LA.begin());

    // cerr << i << ' ' << val[i] << ' ' << nxt[i] << '\n';

    // if(val[i] >= INF) break;

    int j = nxtA[i];               //!!!!!

    if(j > N-1) break;

    if(long_absval(A[ I_A[i] ] - A[ I_A[j] ]) >= long_absval(B[ I_A[i] ] - B[ I_A[j] ]))
    {
        res.insert(long_absval(A[ I_A[i] ] - A[ I_A[j] ]));
        // cerr << I_A[i] << ' ' << I_A[j] << ' ' << abs(A[ I_A[i] ] - A[ I_A[j] ]) << '\n';
    }
    nxtA[i]++;
    compute_score_A(i);

    LA.insert(loc{i, valA[i]});
}












// cerr << "switching \n";





//Part 2: iterate over I_B;
nxtB = vector<int>(N);
for(int i = 0; i < N; i++)
{
    nxtB[i] = i+1;
}

valB = vector<long long>(N, INF);
for(int i = 0; i < N; i++)
{
    compute_score_B(i);
}

set<loc> LB;
for(int i = 0; i < N; i++) LB.insert(loc{i, valB[i]});


++++++++++++

// cerr << "hello\n";

while(res.size() < 2*K)
{
    int i = LB.begin()->i;

    LB.erase(LB.begin());

    int j = nxtB[i];               //!!!!!

    // cerr << i << ' ' << val[i] << ' ' << nxt[i] << '\n';

    if(j > N-1) break;

    if(long_absval(B[ I_B[i] ] - B[ I_B[j] ]) > long_absval(A[ I_B[i] ] - A[ I_B[j] ]))
    {
        res.insert(long_absval(B[ I_B[i] ] - B[ I_B[j] ]));
        // cerr << I_B[i] << ' ' << I_B[j] << ' ' << abs(B[ I_B[i] ] - B[ I_B[j] ]) << '\n';
    }
    nxtB[i]++;
    compute_score_B(i);

    LB.insert(loc{i, valB[i]});
}




*/

Compilation message (stderr)

road_construction.cpp: In function 'int main()':
road_construction.cpp:150:22: warning: comparison of integer expressions of different signedness: 'std::multiset<long long int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  150 |     while(res.size() < K)
      |           ~~~~~~~~~~~^~~
#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...