#define _CRT_SECURE_NO_WARNINGS
#include "maklib.h"
#include "message.h"

#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <vector>

typedef long long lLong;
typedef unsigned long uLong;
typedef unsigned long long ulLong;
typedef unsigned int uInt;
typedef unsigned char Byte;

using namespace std;

#define FOR(x, b, e) for(int x=b; x<=(e); ++x)
#define ALL(i) (i).begin(), (i).end()
#define CONTAINS(i,v) (find(ALL(i),v)!=(i).end())
typedef vector<bool> bit_vector;
typedef vector<ulLong> VI;
typedef vector<ulLong> VLL;


//Implementacja algorytmu Kadane'a - ródło - Wikipedia z drobnymi modyfikacjami
inline lLong MaxSuma(uLong startPos, uLong borderPos, uLong elementCnt)
{
        // Initialize variables here
        int max_so_far  = ElementAt(startPos);
		int max_ending_here = ElementAt(startPos);
 
        // OPTIONAL: These variables can be added in to track the position of the subarray
        // size_t begin = 0;
        // size_t begin_temp = 0;
        // size_t end = 0;
 
        // Find sequence by looping through
        for(lLong i = startPos+1; i <= elementCnt; i++)
        {
                // calculate max_ending_here
                if(max_ending_here < 0)
                {
                        max_ending_here = ElementAt(i);
 
                        // begin_temp = i;
                }
                else
                {
                        max_ending_here += ElementAt(i);
                }
 
                // calculate max_so_far
                if(max_ending_here >= max_so_far )
                {
                        max_so_far  = max_ending_here;
 
                        // begin = begin_temp;
                        // end = i;
						if(i>borderPos)
						{
							break;
						}
                }
        }
        return max_so_far ;
}




int main(int argc, char **argv)
{		
	lLong N = Size();

	int myId=MyNodeId();
	int numOfNodes = NumberOfNodes();

	lLong poczatek = ((MyNodeId() * N) / NumberOfNodes()) + 1;
	lLong koniec = (((MyNodeId() + 1) * N) / NumberOfNodes()) + 1;
	
	// Znajdz max podtablice w przydzileonym bloku
	lLong suma=MaxSuma(poczatek,koniec,N);
	
	// moduly rozproszone zwracaja swoje wyniki do bazy
	if(myId>0)
	{
		PutLL(0,suma);
		Send(0);
	}
	else
	{		
		// modul glowny wybiera max sume z wynikow
		for(lLong i=1;i<numOfNodes;i++)
		{
			int instancja = Receive(-1);
			lLong sumaInst = GetLL(instancja);
			suma = max(suma,sumaInst);
		}
		printf("%lld\n",suma);
	}	
	return 0;
}
