This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <ctime>
using namespace std;
const int INFINI = 1000 * 1000 * 1000;
struct Inter {
int chaine, dist;
int nums[2];
Inter() {
chaine = INFINI;
nums[0] = nums[1] = -1;
dist = INFINI;
}
void push(int _chaine, int _num, int _dist) {
if(_dist < dist) {
dist = _dist;
chaine = _chaine;
nums[0] = _num;
nums[1] = -1;
}
else if(_dist == dist) {
if(nums[0] != _num) {
nums[1] = _num;
}
}
}
};
int nbStations, nbTypes, nbReqs;
int hauteur[100 * 1000];
int suiv[100 * 1000], prec[100 * 1000];
void calculeTransitions() {
vector<int> ids;
for(int iStation = 0;iStation < nbStations;iStation++) {
while(!ids.empty() && hauteur[ids.back()] < hauteur[iStation]) {
suiv[ids.back()] = iStation;
ids.pop_back();
}
if(ids.empty()) {
prec[iStation] = -1;
}
else {
prec[iStation] = ids.back();
}
while(!ids.empty() && hauteur[ids.back()] == hauteur[iStation]) {
suiv[ids.back()] = iStation;
ids.pop_back();
}
ids.push_back(iStation);
}
while(!ids.empty()) {
suiv[ids.back()] = -1;
ids.pop_back();
}
}
vector<vector<int>> chaines;
vector<int> fils[100 * 1000];
vector<int> parent;
int chaine[100 * 1000];
int cur_event = 0;
int in[100 * 1000], out[100 * 1000];
void calculeInters(int chaine = 0) {
in[chaine] = cur_event++;
for(int suiv : fils[chaine]) {
calculeInters(suiv);
}
out[chaine] = cur_event++;
}
bool estFils(int a, int b) {
return in[b] <= in[a] && out[a] <= out[b];
}
void calculeChaines() {
vector<pair<int, int>> stations;
int cur_chaine[100 * 1000];
cur_chaine[0] = 0;
parent.push_back(-1);
chaines.push_back({0});
for(int iStation = 1;iStation < nbStations;iStation++) {
cur_chaine[iStation] = -1;
stations.push_back({hauteur[iStation], iStation});
}
sort(stations.begin(), stations.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
if(a.first != b.first)
return a.first > b.first;
return a.second < b.second;
});
for(pair<int, int> station : stations) {
int id = station.second;
if(hauteur[prec[id]] != hauteur[id]) {
int cur_parent = cur_chaine[prec[id]];
cur_chaine[prec[id]] = chaines.size();
cur_chaine[id] = chaines.size();
chaine[id] = chaines.size();
fils[cur_parent].push_back(chaines.size());
chaines.push_back({prec[id], id});
parent.push_back(cur_parent);
}
else {
cur_chaine[id] = cur_chaine[prec[id]];
chaine[id] = cur_chaine[id];
chaines[chaine[id]].push_back(id);
}
if(suiv[id] != -1 && hauteur[suiv[id]] != hauteur[id]) {
chaines[chaine[id]].push_back(suiv[id]);
}
}
}
vector<Inter> remontes[17][100 * 1000];
inline int getNum(int chaine, int elem) {
return lower_bound(chaines[chaine].begin(), chaines[chaine].end(), elem) - chaines[chaine].begin();
}
inline Inter remonte(Inter& bests, int hauteur) {
Inter coords;
for(int iNumD = 0;iNumD < 2;iNumD++) {
int numD = bests.nums[iNumD];
if(numD == -1) continue;
Inter bestsS = remontes[hauteur][bests.chaine][numD];
for(int iNumS = 0;iNumS < 2;iNumS++) {
int numS = bestsS.nums[iNumS];
if(numS == -1) continue;
coords.push(bestsS.chaine, numS, bestsS.dist + bests.dist);
}
}
return coords;
}
inline void calculeBests() {
for(int iChaine = 0;iChaine < (int)chaines.size();iChaine++) {
vector<int> cur_chaine = chaines[iChaine];
for(int iElem = 0;iElem < (int)cur_chaine.size();iElem++) {
Inter coords;
if(parent[iChaine] == -1) {
coords.push(iChaine, iElem, 0);
remontes[0][iChaine].push_back(coords);
}
else {
coords.push(parent[iChaine], getNum(parent[iChaine], cur_chaine[0]), iElem);
coords.push(parent[iChaine], getNum(parent[iChaine], cur_chaine.back()), cur_chaine.size() - iElem - 1);
remontes[0][iChaine].push_back(coords);
}
}
}
for(int iHauteur = 1;iHauteur < 17;iHauteur++) {
for(int iChaine = 0;iChaine < (int)chaines.size();iChaine++) {
vector<int> cur_chaine = chaines[iChaine];
for(int iElem = 0;iElem < (int)cur_chaine.size();iElem++) {
Inter coords = remonte(remontes[iHauteur - 1][iChaine][iElem], iHauteur - 1);
remontes[iHauteur][iChaine].push_back(coords);
}
}
}
}
inline Inter remonteJusque(Inter deb, int chaine) {
if(estFils(chaine, deb.chaine))
return deb;
Inter cur = deb;
for(int iHauteur = 16;iHauteur >= 0;iHauteur--) {
Inter rem = remonte(cur, iHauteur);
if(!estFils(chaine, rem.chaine)) {
cur = rem;
}
}
return remonte(cur, 0);
}
inline int modulo(int a, int mod) {
return (((a % mod) + mod) % mod);
}
inline int distMod(int a, int b, int mod) {
return min(modulo(a - b, mod), mod - modulo(a - b, mod));
}
inline int distEntre(int deb, int fin) {
Inter debCoord;
debCoord.push(chaine[deb], getNum(chaine[deb], deb), 0);
Inter finCoord;
finCoord.push(chaine[fin], getNum(chaine[fin], fin), 0);
Inter bestsDeb = remonteJusque(debCoord, chaine[fin]);
Inter bestsFin = remonteJusque(finCoord, chaine[deb]);
int minDist = 1000 * 1000;
for(int iNumD = 0;iNumD < 2;iNumD++) {
int numD = bestsDeb.nums[iNumD];
if(numD == -1) continue;
for(int iNumF = 0;iNumF < 2;iNumF++) {
int numF = bestsFin.nums[iNumF];
if(numF == -1) continue;
if(bestsDeb.chaine == 0) {
minDist = min(minDist, bestsDeb.dist + bestsFin.dist + abs(numD - numF));
}
else {
minDist = min(minDist, bestsDeb.dist + bestsFin.dist + distMod(numD, numF, chaines[bestsDeb.chaine].size()));
}
}
}
return minDist;
}
int main() {
scanf("%d%d%d", &nbStations, &nbTypes, &nbReqs);
for(int iStation = 0;iStation < nbStations;iStation++) {
scanf("%d", &hauteur[iStation]);
hauteur[iStation]--;
}
calculeTransitions();
calculeChaines();
calculeInters();
calculeBests();
for(int iReq = 0;iReq < nbReqs;iReq++) {
int deb, fin;
scanf("%d%d", &deb, &fin);
deb--; fin--;
printf("%d\n", distEntre(deb, fin) - 1);
}
return 0;
}
Compilation message (stderr)
railway_trip.cpp: In function 'int main()':
railway_trip.cpp:240:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d%d", &nbStations, &nbTypes, &nbReqs);
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
railway_trip.cpp:243:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d", &hauteur[iStation]);
~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
railway_trip.cpp:254:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d%d", &deb, &fin);
~~~~~^~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |