Submission #108926

#TimeUsernameProblemLanguageResultExecution timeMemory
108926AdrienVannsonTwo Antennas (JOI19_antennas)C++17
35 / 100
3032 ms17772 KiB
#pragma GCC optimize "Ofast,unroll-loops,omit-frame-pointer,inline"

#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;
using ll = long long;

const int oo = 1000*1000*1000;

const int NB_MAX_ANTENNES = 200*1000 + 42;

struct Antenne
{
    int pos;
    int hauteur;
    int distMin, distMax;
};

int nbAntennes;
Antenne antennes[NB_MAX_ANTENNES];


/*
 * Arbre binaire
 */

const int NB_FEUILLES = 1<<18;
const int NB_NOEUDS = 2*NB_FEUILLES;

pair<int, int> valeurs[NB_NOEUDS]; // {min, max}

void setValeur (const int pos, const int nouvelleValeur)
{
    int iNoeud = NB_FEUILLES + pos;

    if (nouvelleValeur == -1) {
        valeurs[iNoeud] = make_pair(+oo, -oo);
    }
    else {
        valeurs[iNoeud] = make_pair(nouvelleValeur, nouvelleValeur);
    }

    for (iNoeud/=2; iNoeud>=1; iNoeud/=2) {
        valeurs[iNoeud].first = min(valeurs[iNoeud*2].first, valeurs[iNoeud*2+1].first);
        valeurs[iNoeud].second = max(valeurs[iNoeud*2].second, valeurs[iNoeud*2+1].second);
    }
}

pair<int, int> getMinmax (const int debut, const int fin,
                          const int iNoeud=1, const int debutActuel=0, const int finActuelle=NB_FEUILLES)
{
    if (debutActuel >= debut && finActuelle <= fin) {
        return valeurs[iNoeud];
    }
    if (debutActuel >= fin || finActuelle <= debut) {
        return make_pair(+oo, -oo);
    }

    const int milieuActuel = (debutActuel + finActuelle) / 2;

    const pair<int, int> res1 = getMinmax(debut, fin, iNoeud*2, debutActuel, milieuActuel);
    const pair<int, int> res2 = getMinmax(debut, fin, iNoeud*2+1, milieuActuel, finActuelle);

    return make_pair( min(res1.first, res2.first), max(res1.second, res2.second) );
}


/*
 * Main
 */

vector<pair<int, int>> evenements[NB_MAX_ANTENNES]; // {pos, 2*iAntenne+estDebut}

int calcRequete (const int debutRequete, const int finRequete)
{
    int res = -1;

    for (int iAntenne=0; iAntenne<nbAntennes; iAntenne++) {
        const Antenne &antenne = antennes[iAntenne];

        // Traiter les événements
        for (const pair<int, int> &evenement : evenements[iAntenne]) {
            const Antenne &ant = antennes[evenement.second / 2];

            if (evenement.second % 2 == 1) { // Début
                setValeur(ant.pos, ant.hauteur);
            }
            else {
                setValeur(ant.pos, -1);
            }
        }

        if (debutRequete <= iAntenne && iAntenne < finRequete) {
            // Trouver le max pour l'antenne actuelle
            const int debut = max(antenne.pos + antenne.distMin, debutRequete);
            const int fin = min(antenne.pos + antenne.distMax + 1, finRequete);

            if (debut >= nbAntennes) {
                continue;
            }

            const pair<int, int> minmax = getMinmax(debut, fin);

            const int score1 = minmax.second - antenne.hauteur;
            const int score2 = antenne.hauteur - minmax.first;

            res = max( max(score1, score2), res );
        }
    }

    return res;
}

int main ()
{
    scanf("%d", &nbAntennes);

    for (int i=0; i<nbAntennes; i++) {
        antennes[i].pos = i;
        scanf("%d %d %d", &antennes[i].hauteur, &antennes[i].distMin, &antennes[i].distMax);

        setValeur(i, -1);
    }

    int nbRequetes;
    scanf("%d", &nbRequetes);

    if (nbAntennes <= 2000) {
        struct Point
        {
            int debut, fin;
            bool estRequete;
            int info; // iRequete ou score

            bool operator< (const Point &autre)
            {
                if (fin != autre.fin) {
                    return fin < autre.fin;
                }
                if (debut != autre.debut) {
                    return debut > autre.debut;
                }
                return !estRequete;
            }
        };

        vector<Point> points;
        int resRequetes[200*1000];

        for (int iRequete=0; iRequete<nbRequetes; iRequete++) {
            int debutRequete, finRequete;
            scanf("%d %d", &debutRequete, &finRequete);
            debutRequete--, finRequete--; // FIN INCLUSE

            points.push_back(Point{debutRequete, finRequete, true, iRequete});
        }

        for (int a=0; a<nbAntennes; a++) {
            for (int b=a+1; b<nbAntennes; b++) {
                if (a < b-antennes[b].distMax || a > b-antennes[b].distMin) {
                    continue;
                }
                if (b > a+antennes[a].distMax || b < a+antennes[a].distMin) {
                    continue;
                }

                points.push_back(Point{a, b, false, abs(antennes[a].hauteur - antennes[b].hauteur)});
            }
        }

        sort(points.begin(), points.end());

        for (const Point &point : points) {

            if (point.estRequete) {
                resRequetes[point.info] = getMinmax(point.debut, nbAntennes).second;

                if (resRequetes[point.info] == -oo) {
                    resRequetes[point.info] = -1;
                }
            }
            else {
                if (point.info > valeurs[NB_FEUILLES+point.debut].second) {
                    setValeur(point.debut, point.info);
                }
            }

        }

        for (int iRequete=0; iRequete<nbRequetes; iRequete++) {
            printf("%d\n", resRequetes[iRequete]);
        }
    }
    else {
        for (int i=0; i<nbAntennes; i++) {
            const Antenne &ant = antennes[i];
            evenements[ max(ant.pos - ant.distMax, 0) ].push_back(make_pair(ant.pos, 2*i+1));
            evenements[ max(ant.pos - ant.distMin + 1, 0) ].push_back(make_pair(ant.pos, 2*i));
        }

        for (int iRequete=0; iRequete<nbRequetes; iRequete++) {
            int debutRequete, finRequete;
            scanf("%d %d", &debutRequete, &finRequete);
            debutRequete--;

            printf("%d\n", calcRequete(debutRequete, finRequete));
        }
    }
}

Compilation message (stderr)

antennas.cpp: In function 'int main()':
antennas.cpp:119:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &nbAntennes);
     ~~~~~^~~~~~~~~~~~~~~~~~~
antennas.cpp:123:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d %d %d", &antennes[i].hauteur, &antennes[i].distMin, &antennes[i].distMax);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
antennas.cpp:129:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &nbRequetes);
     ~~~~~^~~~~~~~~~~~~~~~~~~
antennas.cpp:155:18: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
             scanf("%d %d", &debutRequete, &finRequete);
             ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
antennas.cpp:206:18: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
             scanf("%d %d", &debutRequete, &finRequete);
             ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...