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.

HackerRank Drive problem solution


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();
        
        loadStuff(scan,steps,passengers);
        addPassengers(steps,passengers);
        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>r.deadline){x=r.deadline;}
            if(x>targetSaving){x=(int)targetSaving;}
            
            steps[s].travelTime += x;
            r.deadline -= x;
            targetSaving -= x;
            if ((0<s) && (0 < r.deadline)){
                r.carrying += steps[s].dropped;
                r.station--;
                runs.add(r);
            }
        }
    }
    
    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("deadline : "+String.valueOf(r.deadline));
            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.deadline = steps[i+1].departure - steps[i].departure;
                r.carrying = steps[i+1].dropped;
                runs.add(r);
            }
        }
    }
    
    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;
        }
        return total;
    }
    
    
    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++;
        }
        
        int load=0;
        for (step s : steps){
            load += s.pickedUp - s.dropped;
            s.carried = load;
        }
    }
    
    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 deadline;
    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;

int add(int i) {
    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) {
        cur = add(cur);
    }

    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) 
        {
            x = add(x);
        }
    }
    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;
}
void heap_read(int *size, node *ans)
{
    (*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;
            heap_read(&heap_size, &elem);
        }
        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
            {
                heap_read(&heap_size, &elem);
            }
        }
        else
        {
            ans += elem.w * (long long)k;
            k = 0;
        }
    }
    printf("%lld", ans - start);
    return 0;
}

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