SHROUTE - Editorial

I tried coding up the solution using “upper_bound” and “lower_bound” as well but it seems it doesn’t work for me. If the editorialist can clear this out as to why it doesn’t work for me it will be great.

#include <map>
#include <set>
#include <cstdio>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <algorithm>

using namespace std;

void printVector(vector<int> vec) {
	cout << "printing vector : " << endl;
	for (int i = 0; i < vec.size(); ++i) {
		cout << vec[i] << " ";
	}

	cout << endl;
}

void solve() {
	int N, M; 
	scanf("%d", &N);
	scanf("%d", &M);

	vector<int> Ai(N + 1, 0);
	vector<int> Bi(M + 1, 0);
	vector<int> Ci(M+1, 0);
	vector<int> rightTrains;
	vector<int> leftTrains;

	for (int i = 1; i <= N; ++i) {
		scanf("%d", &Ai[i]);

		if (Ai[i] == 1) {
			rightTrains.push_back(i);
		}

		if (Ai[i] == 2) {
			leftTrains.push_back(i);
		}
	}

	for (int i = 1; i <= M; ++i) {
		scanf("%d", &Bi[i]);
	}

	// sort the vectors for the trains going to the right and the left
	sort(rightTrains.begin(), rightTrains.end());
	sort(leftTrains.begin(), leftTrains.end());

	//printVector(rightTrains);
	// printVector(leftTrains);

	for (int i = 1; i <= M; ++i) {
		// if the destination of the traveller is the first station itself
		// then they are already there and hence time taken is 0
		if (Bi[i] == 1) {
			Ci[i] = 0;
			continue;
		}

		// in the case when every station has 0 trains and the destination
		//  is not 1
		if (rightTrains.size() == 0 && leftTrains.size() == 0) {
			Ci[i] = -1;
			continue;
		}

		int lb, ub;
		lb = ub = -1;

		if (rightTrains.size() != 0) {
			auto lowerBound = lower_bound(rightTrains.begin(), rightTrains.end(), Bi[i]);
			cout << "lowerBound index : " << lowerBound - rightTrains.begin() << endl;
			lb = rightTrains[lowerBound - rightTrains.begin()];
		}

		if (leftTrains.size() != 0) {
			auto upperBound = upper_bound(leftTrains.begin(), leftTrains.end(), Bi[i]);
			cout << "upperBound index : " << upperBound - leftTrains.begin() << endl;
			ub = leftTrains[upperBound - leftTrains.begin()];
		}

		cout << "lb : " << lb << " ub : " << ub << endl;

		if (lb != -1 && ub == -1) {
			Ci[i] = abs(lb - Bi[i]);
			continue;
		}

		if (lb == -1 && ub != -1) {
			Ci[i] = abs(ub - Bi[i]);
			continue;
		}

		Ci[i] = min(abs(lb - Bi[i]), abs(ub - Bi[i]));
	}

	for (int i = 1; i <= M-1; ++i) {
		printf("%d ", Ci[i]);
	}
	
	printf("%d\n", Ci[M]);
}

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

	while (T--) {
		solve();
	}
}

Can you guys make a review on my solution. I merged both left and right train directions in a common vector like in a Dijsktra algorithm but it didn’t work for me. I’m not sure if it was an I/O issue because I ran many sample tests and it always gave me the correct answer. Thanks for your help. Here is my solution in C++:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int T;
    scanf("%d\n", &T);
    for (int i = 0; i < T; i++)
    {
        int N, M;
        scanf("%d %d\n", &N, &M);

        vector<int> dist(N, INT_MAX);

        dist[0] = 0;

        // Building the distance vector
        for (int i = 0; i < N; i++)
        {
            int direction;
            scanf("%d", &direction);
            if ((direction == 1)) {
                dist[i] = 0;
                int j = 1;
                while ((i + j < N) && (dist[i + j] > j)) dist[i + j] = j, j++;
            }
            else if (direction == 2) {
                dist[i] = 0;
                int j = 1;
                while ((i - j >= 0) && (dist[i - j] > j)) dist[i - j] = j, j++;
            }
        }

        for (int i = 0; i < M; i++)
        {
            int destiny;
            scanf("%d", &destiny);
            printf("%d ", (dist[destiny - 1] != INT_MAX)? dist[destiny - 1] : -1);
        }

        printf("\n");
    }

    return 0;
}

I did it with mower bound and it passed all cases

#include <bits/stdc++.h>
using namespace std;

int main() {
// your code goes here
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin>>t;
while(t–){
int n,m;
cin>>n>>m;
multimap<int, int> mp1;
multimap<int, int> mp2;
for(int i=1; i<=n; ++i){
int x;
cin>>x;
if(x==1){
mp1.insert({i,1});
}
else if(x==2){
mp2.insert({i,2});
}
}
int size1 = mp1.size();
int size2 = mp2.size();

    for(int i=1; i<=m; ++i){
        int x;
        cin>>x;
        if(x==1){
            cout<<0<<" ";
        }
        else{
            auto it1 = mp1.lower_bound(x);
	        auto it2 = mp2.lower_bound(x);
	        int behind = -1;
	        int next = -1;
	        if((it1->first==x && it1->second!=0) || (it2->first==x && it2->second!=0)){
	            behind=0;
	            next=0;
	        }else{
	            if(it1->second!=0){
	                auto f=mp1.begin();
	                if(f->first == it1->first)
	                    behind=-1;
	                else{
	                    it1--;
	                    behind = x-(it1->first);
	                }
	            }
	            else{
	                if(size1>0){
	                    --it1;
	                    if(it1->second!=0)
	                        behind = x - (it1->first);
	                    else
	                        behind=-1;
	                }
	                else{
	                    behind = -1;
	                }
	            }
	            if(it2->second!=0){
	                next=(it2->first)-x;
	            }
	            else{
	                next = -1;
	            }
	        }
	        
	        if(behind==-1&&next==-1){
	            cout<<-1<<" ";
	        }
	        else if(behind == -1&& next!=-1){
	            cout<<next<<" ";
	        }
	        else if(behind!=-1&& next==-1){
	            cout<<behind<<" ";
	        }
	        else{
	            cout<<min(behind, next)<<" ";
	        }
        }
    }
    cout<<endl;
}
return 0;

}

4 Likes

Care to format your code and put it in a spoiler before posting or rather share a link if you really want to help.

Yeah i’ll take care of that in future

4 Likes

Somewhat readable c++ solution

I don’t see any c++ submission by you for this problem

Can’t understand why my solution is giving TLE? I have implemented it in O(n).
Please take a look.

https://www.codechef.com/viewsolution/47838720

vectors were slow for this problem, i used c typed arrays to get away.

But in the Tester’s solution and in the video editorials they used vectors.

1 Like

although I haven’t spent much time on your code but I can see two while loops inside your for loops and I think there might be the TLE.

3 Likes

You are partially correct. Please look at it once more. I am still getting TLE.

Can someone please tell me what’s wrong with this solution , i was getting tle.

import sys
t = int(input())
for i in range(t):

# taking input
n, m = map(int, sys.stdin.readline().split(' '))
direction = list(map(int, sys.stdin.readline().split(' ')))
travellers = list(map(int, sys.stdin.readline().split(' ')))

# logic
for destination in travellers:
    if direction[destination - 1] != 0 or destination == 1:
        print(0)
    else:
        s1 = n
        s2 = n
        if 1 in direction[:destination - 1]:
            l = direction[:destination - 1]
            l.reverse()
            temp = l.index(1) - len(l) + 1
            s1 = (destination - 1) - temp
        if 2 in direction[destination:]:
            l = direction[destination:]
            temp = l.index(2) + destination
            s2 = temp - (destination - 1)

        if s1 == n and s2 == n :
            print(-1)
        else:
            print(min(s1,s2))

Hi can anyone help me find what is wrong with my solution?
It’s almost similar to Editorials solution, but I got Wrong Answer

#include<iostream>
#include<string>
#include<vector>
#include<math.h>
#include<algorithm>
#include <bits/stdc++.h>

using namespace std;
long long int best[100002];
long long int A[100002];
long long int B[100002];
int main()
{
    // ios_base::sync_with_stdio(0);
	// cin.tie(0);
	// cout.tie(0);
    long long int T;
    cin>>T;
    while (T--)
    {
        long long int N,M,a,b;
        cin>>N>>M;
        long long int left = -1,right=N;
        for(long long int i=0;i<N;i++)
        {
            best[i] = -1;
        }
        for(long long int i=0;i<N;i++)
        {
            cin>>A[i];
        }
        for(long long int i=0;i<M;i++)
        {
            cin>>B[i];
        }
        for(long long int i=0;i<N;i++)
        {
            if(A[i] == 1)
                left = i;
            if(left != -1)
                best[i] = i-left;
        }
        for(long long int i=N-1;i>=0;i--)
        {
            if(A[i] == 2)
                right = i;
            
            if(right != N)
                if((best[i] == -1) || (best[i] > (right-i)))
                    best[i] = right - i;
        }
        for(long long int i=0;i<M;i++)
        {
            cout<<best[B[i]-1]<<" ";
        }
        cout<<"\n";
    }
}

Solution using Dijkstra’s Algorithm

abhijeetgupto - if you process the full city set for every query, you will be doing far too much data handling. Much better to separate out the up-train and down-train cities and then use those either to search for suitable journey start points or pre-process to a time map; something like:

    ups = []
    downs = [0]
    for city, dirn in enumerate(trains, start=1):
        if dirn == 1:
            ups.append(city)
        elif dirn == 2:
            downs.append(city)

However: if you hadn’t gotten TLE, you would have gotten WA. The results from a single test case are supposed to be delivered on a single line of space-separated values.

Fast output is as important as fast input in this case - you need to limit your print statements.

my solution code CodeChef: Practical coding for everyone

Simple C++ solution. O(n) time complexity.

  #include <iostream>
    using namespace std;
    void solve()
    {
    int stationSize,destinationSize;
    vector<int> stations,destinations;
    cin>>stationSize>>destinationSize;
    int in;

    for(int i=0;i<stationSize;i++){
    cin>>in;
    stations.push_back(in);
    }
    for(int i=0;i<destinationSize;i++){
    cin>>in;
    destinations.push_back(in);
    }

    vector<int> distanceArray;
    distanceArray.assign(stations.size(),INT_MAX);
    distanceArray[0]=0;

    int counter=0,lastRightTrain=-1,lastLeftTrain=-1;
    //left to right pass
    for(int i=0;i<stationSize;i++){
    if(stations[i]==1){
        lastRightTrain=i;
    }
    if(stations[i]==1 || stations[i]==2){
        distanceArray[i]=0;
    }
    else if(stations[i]==0){
        distanceArray[i]=lastRightTrain==-1?distanceArray[i]:(i-lastRightTrain);
    }
    }


    //right to left pass
    for(int i=stationSize-1;i>=0;i--){
    if(stations[i]==2){
        lastLeftTrain=i;
    }
    if(stations[i]==0){
        distanceArray[i]=lastLeftTrain==-1?distanceArray[i]:min(distanceArray[i],lastLeftTrain-i);
    }
    }

    for(int i=0;i<destinationSize;i++){
    int a=distanceArray[destinations[i]-1]==INT_MAX?-1:distanceArray[destinations[i]-1];
    cout<<a<<" ";
    }

    cout<<endl;

    }

    int main()
    {

    int t;
    cin>>t;
    while (t--)
    {
        solve();
    }
    }
2 Likes

Couple of Python solutions for interest:

Precalculated time array

Binary search per destination (slower)

#include

#include<bits/stdc++.h>

using namespace std;

int main(){

void solution(long long,long long);

int t;

cin>>t;

while(t){

    long long  n,m;

    cin>>n>>m;

    solution(n,m);

    cout<<endl;

    t--;

}

return 0;

}

void solution(long long n,long long m){

    long long x,i,y;

    vector<long long> a(n,0);

    vector<long long> b(m,0);

    vector<long long> start(n,0);

    vector<long long> ends(n,0);

    for(i=0;i<n;i++) cin>>a[i];

    for(int j=0;j<m;j++) cin>>b[j];

    if(a[0]==2||a[0]==0){

        for(int i=0;i<m;i++){

            if(b[i]==1) cout<<0<<" ";

            else cout<<-1<<" ";

        }

    }else{

        int x=-1;

        for(i=0;i<n;i++){

            if(a[i]==1){

            start[i]=i;

            x=i;

            }else{

              start[i]=x;

            }

        }

        x=-1;

        for(i=n-1;i>=0;i--){

            if(a[i]==2){

                ends[i]=i;

                x=i;

            }else{

                ends[i]=x;

            }

        }

        for(i=0;i<m;i++){

            long long index = b[i]-1;

            if(b[i]==1||a[index]==1||a[index]==2) cout<<0<<" ";

            else {

                if(ends[index]==-1) cout<<index-start[index]<<" ";

                else cout<<min(ends[index]-index,index-start[index])<<" ";

            }

        }

    }

}