#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <map> 
#include <string>
#include <vector>  
#include <iostream> 
#include <sstream> 
#include <queue>
#include <algorithm> 
#include <assert.h>
#include "dzialka.h"
#include "message.h"

using namespace std;

#define ll long long
#define PB 		push_back
#define FOR(a,start,end) 	for(int a=int(start); a<int(end); a++)
#define INF 		INT_MAX
#define SORT(a) 	sort(a.begin(),a.end()) 
#define CL(a,x) 		memset(a,x,sizeof(a))
#define REP(a,x)	for(int a=0;a<x;a++)
#define REP1(a,x)	for(int a=1;a<=x;a++)
#define MP 		make_pair



typedef vector<ll>     vi;
typedef pair<ll, ll>     pii;
typedef vector<string> vs;
typedef vector<pii> vii;
typedef vector<vector<ll> > vvi;
typedef vector<vector<string> > vvs;
typedef vector<pair<string, string> > vss;
typedef pair<string, string> pss;
typedef pair<ll, pii> ppii;
typedef vector<ppii> vppii;
typedef vector<vector<pii> > vvii;
typedef vector<vvi> vvvi;

int w, h, m;
ll nz;
ll n, k, z, a, b, c, d, z0;
vi vk;
vii vkx, vkx1;

ll dod(void) {
	ll z = 0ll;
	ll a, k, b;
	//	for(int i=0;i<vkx.size();i++)
	//		cerr<<vkx[i].first<<" "<<vkx[i].second<<endl;
	a = vkx.back().first;
	k = vkx.back().second;
	for (int i = vkx.size() - 2; i >= 0; i--) {
		b = k - vkx[i].second;
		z += a * b;
		a = vkx[i].first;
		k = vkx[i].second;
	}
	return z;
}
ll dod2(void) {
	ll z = 0ll;
	ll a1, a, k, b;
	int i, i1;

	a = vkx.back().first;
	k = vkx.back().second;
	a1 = vkx1.back().first;
	i = (int)vkx.size() - 2;
	i1 = (int)vkx1.size() - 2;
	while (i >= 0 && i1 >= 0) {

		if (vkx[i].second<vkx1[i1].second) {
			b = k - vkx1[i1].second;
			z += a * a1*b;
			a1 = vkx1[i1].first;

			k = vkx1[i1].second;
			i1--;
		}
		else if (vkx[i].second>vkx1[i1].second) {
			b = k - vkx[i].second;
			z += a * a1*b;
			a = vkx[i].first;

			k = vkx[i].second;
			i--;
		}
		else {
			b = k - vkx[i].second;
			z += a * a1*b;
			a = vkx[i].first;
			a1 = vkx1[i1].first;

			k = vkx[i].second;
			i--;
			i1--;
		}
		/*
		if(m==4&&a*a1*b<0){
		cerr<<"vkx = ";
		for(int i=0;i<vkx.size();i++)
		cerr<<vkx[i].second<<" ";
		cerr<<endl;
		cerr<<"vkx1 = ";
		for(int i=0;i<vkx1.size();i++)
		cerr<<vkx1[i].second<<" ";
		cerr<<endl;
		cerr<<" blad dod2 "<<a<<" "<<a1<<" "<<b<<endl;
		while(1);
		}
		*/
	}
	return z;
}


int main() {
	//freopen( "c:\\wojtek\\uva\\pa\\debug\\t1.in", "rt", stdin);  

	//pi=2*acos(0.0);

	m = MyNodeId();
	nz = (ll)NumberOfNodes();

	w = GetFieldWidth();
	h = GetFieldHeight();
	//	if(m==4){
	//		cerr<<"m = "<<m<<" nz = "<<nz<<" w = "<<w<<" h = "<<h<<endl;
	//	}
	if (h<100) {
		if (m == 0) {
			//		cerr<<"m = "<<m<<" nz = "<<nz<<" w = "<<w<<" h = "<<h<<endl;
			vk.assign(w, 0ll);

			z = 0ll;
			for (int i = 0; i<h; i++) {
				vkx.clear();
				vkx.push_back(MP(0ll, -1ll));
				for (int j = 0; j<w; j++) {
					if (IsUsableCell(i, j)) {
						vk[j]++;
						//		cerr<<" i, j,vk[j] "<<i<<" "<<j<<" "<<vk[j]<<endl;
						for (int jx = (int)vkx.size() - 1; jx>0; jx--) {
							if (vkx[jx].first >= vk[j])
								vkx.pop_back();
							else
								break;
						}
						vkx.push_back(MP(vk[j], (ll)j));
						z += dod();
						//		cerr<<z<<endl;
					}
					else {
						vkx.clear();
						vkx.push_back(MP(0ll, (ll)j));
						vk[j] = 0ll;
					}
				}
				//	for(int ix=0;ix<w;ix++)
				//		cerr<<vk[ix]<<" ";
				//	cerr<<endl;
			}

			cout << z << endl;
		}
	}
	else {
		k = h / nz;    //ile wierszy w każdej instancji

		int k1 = m * k;
		int k2 = (m + 1)*k - 1;
		if (m == nz - 1)
			k2 = h - 1;
		//	if(m==4)
		//		cerr<<"k = "<<k<<" k1 = "<<k1<<" k2 = "<<k2<<endl;
		//
		vk.assign(w, 0ll);
		vi vk1;
		vk1.assign(w, -1ll);
		z = 0ll;
		for (int i = k1; i <= k2; i++) {
			vkx.clear();
			vkx.push_back(MP(0ll, -1ll));
			for (int j = 0; j<w; j++) {
				if (IsUsableCell(i, j)) {
					vk[j]++;
					for (int jx = (int)vkx.size() - 1; jx>0; jx--) {
						if (vkx[jx].first >= vk[j])
							vkx.pop_back();
						else
							break;
					}
					vkx.push_back(MP(vk[j], (ll)j));
					z += dod();
				}
				else {
					vkx.clear();
					vkx.push_back(MP(0ll, (ll)j));
					if (vk1[j] < 0ll)
						vk1[j] = vk[j];
					vk[j] = 0ll;
				}
			}
		}
		for (int j = 0; j < w; j++) {
			if (vk1[j] < 0ll)
				vk1[j] = vk[j];
		}
		//	if(m==4)
		//		cerr<<"z = "<<z<<endl;

		if (m>0) {
			/*
			vi vk1;
			vk1.assign(w, 0ll);
			for (int j = 0; j<w; j++) {
				int i = k1;
				ll a = 0;
				while (i <= k2 && IsUsableCell(i, j)) {
					a++;
					i++;
				}
				vk1[j] = a;
			}
			*/
			//	Receive(m-1);
			//	ll z0=GetLL(m-1);
			//	z+=z0;
			vi vk0;
			vk0.assign(w, 0ll);
			//	cerr<<"node "<<m<<" received "<<z0<<" from node "<<m-1<<endl;

			int i = 0;
			int imax = 15000;
			while (i<w) {


				Receive(m - 1);
				for (; i<min(imax, w); i++) {
					vk0[i] = (ll)GetInt(m - 1);
				}
				imax += 15000;
			}

			//mamy vk1 i vk0;
			vkx.clear();
			vkx.push_back(MP(0ll, -1ll));
			vkx1.clear();
			vkx1.push_back(MP(0ll, -1ll));
			//
			for (int j = 0; j<w; j++) {
				if ((vk0[j] != 0ll) && (vk1[j] != 0ll)) {

					for (int jx = (int)vkx.size() - 1; jx>0; jx--) {
						if (vkx[jx].first >= vk0[j])
							vkx.pop_back();
						else
							break;
					}
					vkx.push_back(MP(vk0[j], (ll)j));
					for (int jx = (int)vkx1.size() - 1; jx>0; jx--) {
						if (vkx1[jx].first >= vk1[j])
							vkx1.pop_back();
						else
							break;
					}
					vkx1.push_back(MP(vk1[j], (ll)j));
					//		if(m==4&&vkx1.back().second!=vkx.back().second)
					//			cerr<<"blad "<<vkx1.back().second<<" "<<vkx.back().second<<endl;
					z += dod2();
				}
				else {
					//	if((vk0[j]==0)||(vk1[j]==0)){
					vkx.clear();
					vkx.push_back(MP(0ll, (ll)j));
					//	}
					//	if(vk1[j]==0){
					vkx1.clear();
					vkx1.push_back(MP(0ll, (ll)j));
				}

				if (vk[j] == k2 - k1 + 1)
					vk[j] += vk0[j];
			}
			//
			Receive(m - 1);
			z0 = GetLL(m - 1);
			//	if(m==4)
			//		cerr<<"node "<<m<<" received "<<z0<<" from node "<<m-1<<endl;
			z += z0;
			//	if(m==4)
			//		cerr<<" z2 = "<<z<<endl;

		}
		if (m<nz - 1) {

			int i = 0;
			int imax = 15000;
			while (i<w) {

				for (; i<min(imax, w); i++) {
					PutInt(m + 1, (int)vk[i]);
				}
				Send(m + 1);
				imax += 15000;

			}

			PutLL(m + 1, z);
			//	if(m<5)
			//		cerr<<"node "<<m<<" sent "<<z<<" to node "<<m+1<<endl;
			//	if(m==98)
			//		cerr<<"node "<<m<<" sent "<<z<<" to node "<<m+1<<endl;
			Send(m + 1);

		}
		else {
			cout << z << endl;
		}



	}






	//czas = clock() - czas;
	//printf("%lf\n",double(czas)/CLOCKS_PER_SEC);					
	//}

	return 0;

}
