#include <algorithm>
#include <iostream>
#include <vector>

#include "krazki.h"
#include "message.h"

using namespace std;



//dopasujace od 0 do n-1
//otwor od dolu
long long int hole(int i, int n){

    return HoleDiameter(    (long long int)   ( n-i  )        );
}
//OD DOLU 0 ->N-1
long long int disc(int i){
    return DiscDiameter((long long int) (i+1) );
}

int main()
{
    int n, m;
    int inst = MyNodeId();
    int all = NumberOfNodes();
    n = PipeHeight();
    m = NumberOfDiscs();

    int a = n* inst/all;
    int b = n* (inst+1) /all;

    int l = b-a;


    vector<long long int> wides;
    wides.resize(l);
    long long int mini = hole(n-1, n);
    for(int i=l-1; i>=0; --i){
        int x = hole(a+i, n);
        if(x<mini) mini = x;
        wides[a+i]=mini;
    }
    long long int gorne_ograniczenie = hole(n-1, n);
    if(inst!=all-1){
         Receive(inst+1);
         gorne_ograniczenie = GetLL(inst+1);
    }
    if(inst!=0){
        PutLL(inst-1, min(gorne_ograniczenie, wides[0]));
        Send(inst-1);
    }
    for(int i=l-1; i>=0; --i){
        if(wides[i]>gorne_ograniczenie) wides[i]=gorne_ograniczenie;
        else break;
    }
    //Zrobilem lejek!!!

    //Teraz czesc glowna


    int uzyte = 0;
    vector<long long int>::iterator najwyzszy=wides.begin();
    long long int * czy_cos_tu = new long long int[l];

    for(int i=a; i<min(b, m); ++i){
        long long int szukana = disc(i);
          vector<long long int>::iterator pozycja = lower_bound(najwyzszy, wides.end(), szukana);
        if(pozycja == wides.end()){
            najwyzszy = pozycja;
            break;
        }
        else{
            najwyzszy = pozycja;
            ++najwyzszy;
            ++uzyte;
            //COŚ
        }
    }


    int wchodzi_z_dolu=0;
    if(inst!=0){
        Receive(inst-1);
        wchodzi_z_dolu = GetInt(inst-1);
    }


    int wypychane_do_gory=0;
    int uzyte2=0;
    int gdzie_dopchnal=0;

    if(wchodzi_z_dolu){
        vector<long long int>::iterator najwyzszy2=wides.begin();

        //jesli zaczynam od a i weszlo mi c, to od a-c do a-1


        for(int i=a-wchodzi_z_dolu; i<a; ++i){
            long long int szukana = disc(i);
            vector<long long int>::iterator pozycja = lower_bound(najwyzszy, wides.end(), szukana);
            if(pozycja == wides.end()){
                break;
            }
            else{
                najwyzszy2 = pozycja;
                ++najwyzszy2;
                ++uzyte2;
                //COŚ
            }
        }
        gdzie_dopchnal = std::distance(wides.begin(), najwyzszy2);
    }
    int dane_tutaj = max( min(b,m)-a, 0);
    ///uzyte
    wypychane_do_gory = dane_tutaj - uzyte + wchodzi_z_dolu - uzyte2 + max(0, uzyte-(l-gdzie_dopchnal)+1); ///sprawdzic l -gdzie
    ///

    if(inst!=all-1){
        PutInt(inst+1, wypychane_do_gory);
        Send(inst+1);
    }
    else{
        if(wypychane_do_gory) cout << 0;
        else{
            cout << n - max(gdzie_dopchnal, (int)distance(wides.begin(), najwyzszy));
        }
    }


    return 0;
}
