In this HackerRank Drive problem solution, The bus is equipped with K units of Nitro (N2O). If going from station one to station two takes x seconds, then using t units of nitro can decrease the time taken to max(x-t, 0) seconds where max(a,b) denotes the greater of the two values between a & b. The Nitro can be used all at once or in multiples of 1 unit.

If the bus driver travels optimally, what is the minimum sum of traveling time for all commuters? The traveling time equals the time he/she arrived at the destination minus the time he/she arrived at the start station.

## Problem solution in Java.

```import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Drive {

public static void main(String[] args)  {
Scanner scan = new Scanner(System.in);

step[] steps = new step[scan.nextInt()];
passenger[] passengers = new passenger[scan.nextInt()];
int nitro = scan.nextInt();

calcDepartures(steps);

Queue<run> runs = new PriorityQueue();
findruns(runs,steps);
saveNitro(steps,runs,nitro);
calcDepartures(steps);
System.out.println(passengerTime(steps,passengers));

}

static void saveNitro(step[] steps,Queue<run> runs,int nitroLimit){
long targetSaving = totalDistance(steps) - nitroLimit;
run r;
int s;
int x;

while(0<targetSaving){
r = runs.poll();
s = r.station;
x = steps[s].distance - steps[s].travelTime;
if(x>targetSaving){x=(int)targetSaving;}

steps[s].travelTime += x;
targetSaving -= x;
if ((0<s) && (0 < r.deadline)){
r.carrying += steps[s].dropped;
r.station--;
}
}
}

static long totalDistance(step[] steps){
long distance=0;
for(step s : steps){
distance += s.distance;
}
return distance;
}

static void printruns(Queue<run> runs){
for(run r : runs){
System.out.println("~~~~~~~~");
System.out.println("station : "+String.valueOf(r.station));
System.out.println("tocarry : "+String.valueOf(r.carrying));
}
}

static void findruns(Queue<run> runs,step[] steps){
steps[steps.length-1].departure = 2000000000;
for(int i=0;i<steps.length-1;i++){
if(steps[i].departure < steps[i+1].departure){
run r = new run();
r.station = i;
r.carrying = steps[i+1].dropped;
}
}
}

static long passengerTime(step[] steps,passenger[] passengers){
long total = 0;
for(passenger p : passengers){
total += steps[p.dest-1].departure + steps[p.dest-1].travelTime - p.arrival;
}
}

static void calcDepartures(step[] steps){
int t = 0;
for (step s : steps){
if(s.departure < t){
s.departure = t;
}else{
t = s.departure;
}
t+=s.travelTime;
}
}

static void addPassengers(step[] steps, passenger[] passengers){
for (passenger p : passengers) {
if(steps[p.start].departure < p.arrival){
steps[p.start].departure = p.arrival;
}
steps[p.start].pickedUp++;
steps[p.dest].dropped++;
}

for (step s : steps){
}
}

static void loadStuff(Scanner scan,step[] steps, passenger[] passengers){
for(int i=0;i<steps.length-1;i++){
steps[i] = new step();
steps[i].distance = scan.nextInt();
steps[i].departure = 0;
steps[i].travelTime = 0;
steps[i].carried = 0;
steps[i].pickedUp = 0;
steps[i].dropped = 0;

}
steps[steps.length-1] = new step();

for(int i=0;i<passengers.length;i++){
passengers[i] = new passenger();
passengers[i].arrival = scan.nextInt();
passengers[i].start = scan.nextInt()-1;
passengers[i].dest = scan.nextInt()-1;
}
}

static void printStations(step[] steps){
for(step s : steps){
System.out.println("-------");
System.out.println("departure : "+String.valueOf(s.departure));
System.out.println("distance : "+String.valueOf(s.distance));
System.out.println("travel time : "+String.valueOf(s.travelTime));
System.out.println("picked up : "+String.valueOf(s.pickedUp));
System.out.println("dropped : "+String.valueOf(s.dropped));
System.out.println("carried : "+String.valueOf(s.carried));
}
}
}

class passenger{
public
int arrival;
int start;
int dest;
}

class step{
public
int departure;
int distance;
int carried;
int pickedUp;
int dropped;
int travelTime;
}

class run implements Comparable<run>{
public
int station;
int carrying;

@Override public int compareTo(run r2){
return (this.carrying - r2.carrying);
}
}```

{"mode":"full","isActive":false}

## Problem solution in C++.

```#include <iostream>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

int n, m, k;
int dist[100100];
int late[100100];
int bin[100100];
int bout[100100];
int arrival[100100];
vector<long long> peop[100100];
long long ans;

void gen() {
cout << 100 << " " << 100 << " " << 1000 << endl;
for(int i = 0; i < 99; ++i) {
cout << rand() % 1000 << " ";
}
for(int i = 0; i < 100; ++i) {
int y = rand() % 100 + 1, x = rand() % y;
cout << rand() % (x * 1000 + 100) << " " << x << " " << y << endl;
}
exit(0);
}

struct st {
int i, j;
long long saved;
int spend;
st(int i, int j, long long saved, int spend) : i(i), j(j), saved(saved), spend(spend) {}
bool operator < (st a) const {
if (saved != a.saved) {
return saved < a.saved;
}
return spend < a.spend;
}
};

priority_queue<st> q;

if (i == n) return n;
int spend = 1000000000;
int j = i + 1;
if (dist[i]) {
spend = min(spend, dist[i]);
long long saved = 0;
for(j = i + 1; j <= n; ++j) {
--arrival[j];
saved += bout[j];
if (late[j] > arrival[j]) {
break;
}
spend = min(spend, arrival[j] - late[j] + 1);
}
if (j > n) j = n;
//cout << i << " = " << j << endl;
st w(i, j, saved, spend);
q.push(w);
for(int q = i + 1; q <= j; ++q) {
++arrival[q];
}
}
return j;
}

int main() {
//gen();
cin >> n >> m >> k;
--n;
for(int i = 0; i < n; ++i) {
cin >> dist[i];
}
for(int i = 0; i < m; ++i) {
int t, s, e;
cin >> t >> s >> e;
--s;
--e;
late[s] = max(late[s], t);
++bout[e];
peop[s].push_back(t);
}
late[n] = -1000000000;

long long nowt = 0, carry = 0;
for(int i = 0; i < n; ++i) {
arrival[i] = nowt;
for(int j = 0; j < peop[i].size(); ++j) {
if (peop[i][j] < nowt) {
ans += nowt - peop[i][j];
} else {
ans += carry * (peop[i][j] - nowt);
}
++carry;
nowt = max(peop[i][j], nowt);
}
ans += carry * dist[i];
nowt += dist[i];
carry -= bout[i + 1];
}
arrival[n] = nowt;

int cur = 0;
while(cur < n) {
}

while(k && !q.empty()) {

st w = q.top();
q.pop();
if (w.spend >= k)
{
ans -= w.saved * k;
break;
}ans -= w.saved * w.spend;
k -= w.spend;
dist[w.i] -= w.spend;
for(int i = w.i + 1; i <= w.j; ++i) {
arrival[i] -= w.spend;
}

int x = w.i;
while(x < w.j)
{
}
}
cout << ans << endl;
return 0;
}
```

{"mode":"full","isActive":false}

## Problem solution in C.

```#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int u;
int cur;
int w;
int c;
}node;
int last_arrive[100000], drop[100001], d[100000], heap_list[100001];
node heap[100001];
void heap_insert(node *elem, int *size)
{
(*size)++;
int index = (*size);
while( index > 1 && elem -> w < heap[index/2].w )
{
heap[index] = heap[index/2];
heap_list[heap[index].u] = index;
index /= 2;
}
heap[index] = (*elem);
heap_list[elem -> u] = index;
return;
}
void heap_update(node *elem, int *size)
{
int index = heap_list[elem -> u];
while( index * 2 <= *size && elem -> w > heap[index*2].w || index * 2 + 1 <= *size && elem -> w > heap[index*2+1].w )
{
index = ( index * 2 + 1 <= *size && heap[index*2].w > heap[index*2+1].w ) ? index * 2 + 1 : index * 2;
heap[index/2] = heap[index];
heap_list[heap[index].u] = index / 2;
}
heap[index] = (*elem);
heap_list[elem -> u] = index;
return;
}
{
(*ans) = heap[1];
int index = 1;
while( index * 2 < *size && heap[*size].w > heap[index*2].w || index * 2 + 1 < *size && heap[*size].w > heap[index*2+1].w )
{
index = ( heap[index*2].w > heap[index*2+1].w ) ? index * 2 + 1 : index * 2;
heap[index/2] = heap[index];
heap_list[heap[index].u] = index / 2;
}
heap[index] = heap[*size];
heap_list[heap[index].u] = index;
(*size)--;
return;
}
int main()
{
int n, m, k, x, y, z, total_use, last_time, heap_size, i;
long long start, ans;
node elem;
scanf("%d%d%d", &n, &m, &k);
for( i = 0 ; i < n - 1 ; i++ )
{
scanf("%d", d + i);
}
for( i = start = 0 ; i < m ; i++ )
{
scanf("%d%d%d", &x, &y, &z);
start += x;
if( x > last_arrive[y-1] )
{
last_arrive[y-1] = x;
}
drop[z-1]++;
}
for( i = n - 2 ; i >= 0 ; i-- )
{
drop[i] += drop[i+1];
}
for( i = ans = total_use = last_time = heap_size = 0 ; i < n ; i++ )
{
if(i)
{
total_use += d[i-1];
}
ans += ( drop[i] - drop[i+1] ) * (long long)last_time;
if( last_arrive[i] > last_time )
{
if(i)
{
elem.u = elem.cur = i;
elem.w = drop[i] - drop[i+1];
elem.c = last_arrive[i] - last_time;
heap_insert(&elem, &heap_size);
}
last_time = last_arrive[i];
}
}
elem.u = elem.cur = n - 1;
elem.w = drop[n-1] - drop[n];
elem.c = 100000000;
heap_insert(&elem, &heap_size);
if( total_use <= k )
{
printf("%lld", ans - start);
return 0;
}
k = total_use - k;
while(k)
{
elem = heap[1];
if( elem.c <= d[elem.cur-1] && elem.c <= k )
{
ans += elem.w * (long long)elem.c;
k -= elem.c;
d[elem.cur-1] -= elem.c;
}
else if( d[elem.cur-1] <= elem.c && d[elem.cur-1] <= k )
{
ans += elem.w * (long long)d[elem.cur-1];
k -= d[elem.cur-1];
elem.c -= d[elem.cur-1];
d[elem.cur-1] = 0;
for( ; elem.cur > 0 && !d[elem.cur-1] ; elem.cur-- );
if(elem.cur)
{
elem.w = drop[elem.cur] - drop[elem.u+1];
heap_update(&elem, &heap_size);
}
else
{
}
}
else
{
ans += elem.w * (long long)k;
k = 0;
}
}
printf("%lld", ans - start);
return 0;
}
```

{"mode":"full","isActive":false}