1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
program Mak3;

{$mode objfpc}{$H+}

uses
   {$IFDEF UNIX}{$IFDEF UseCThreads}
   cthreads,
   {$ENDIF}{$ENDIF}
   Classes, message, maklib
   { you can add units after this };
Type TRec=Record
        Start,Finish:Longint;
        Sum:Int64;
        Used:Boolean;
     End;

Var Id,MaxId:Longint;
    Curent, First, Last, Max:TRec;

Function InitRec:TRec;    // Ustaw Pola;
Begin
   Result.Start :=0;
   Result.Finish:=0;
   Result.Sum   :=0;
   Result.Used  :=False;
End;

Function SetRec(Const ARec:TRec):TRec;inline;
Begin
   Result:=ARec;		    	       // Przepisz Record;
   Result.Used:=True;                          // Ustaw Flage Uzycia
End;

Function GetRec(AInst:Longint):TRec;
Begin
   Result.Start :=GetInt(AInst);
   Result.Finish:=GetInt(AInst);
   Result.Sum   :=GetLL (AInst);
   Result.Used  :=Boolean(GetInt(AInst));
End;

Procedure GetAllRec(AInst:Longint);
Begin
   Receive(AInst);
   First:=GetRec(AInst);
   Max  :=GetRec(AInst);
   Last :=GetRec(AInst);
End;

Procedure PutRec(Const ARec:TRec);
Begin
   PutInt( 0, ARec.Start     );
   PutInt( 0, ARec.Finish    );
   PutLL ( 0, ARec.Sum       );
   PutInt( 0, Byte(ARec.Used));
End;

Procedure FindMax;
Var AStart, AFinish, Loop:LongInt;
Begin
   Receive(0);                             // Obierz wiadomosc od Instancji "0"
   AStart :=GetInt(0);                     // Poczatek przeszukiwanego zakresu
   AFinish:=GetInt(0);			   // Koniec przeszukiwanego zakresu
   Curent:=InitRec;                        // Zeruj rekordy
   First :=InitRec;
   Last  :=InitRec;
   Max   :=InitRec;
   Curent.Start:=AStart;                        // Poczatkowa pozycja
   For Loop:=AStart to AFinish do Begin         // Przeczytaj zakres dla danej Instancji
      Curent.Sum   :=Curent.Sum+ElementAt(Loop);// Dodaj sume
      Curent.Finish:=Loop;                      // Przesun koniec zakresu
      If Curent.Sum>=Max.Sum Then Begin         // Czy wieksza od Maksa
         Max :=SetRec(Curent);                  // Przepisz rekord
      End;
      If Curent.Sum<=0 Then Begin
         Curent.Sum:=0;
         If Not First.Used Then First:=SetRec(Max   );//Ustaw pierwszy Maks
         Curent:=InitRec;
         Curent.Start:=Loop+1;
      End;
   End;
   Curent.Finish:=Loop;
   If Not First.Used Then First:=SetRec(Max);
   Last:=Curent;
   PutRec( First );
   PutRec( Max   );
   PutRec( Last  );
   Send  (0      );
End;

Procedure PrintMax;
var Loop:Longint;
    TotalMax:Int64;
    Prev:TRec;
Begin
   GetAllRec(1);
   TotalMax:=Max.Sum;
   Prev:=Last;
   For Loop:=2 to MaxId-1 do Begin
      GetAllRec(Loop);
      Prev.Sum:=Prev.Sum+First.Sum;
      If Prev.Sum>TotalMax Then TotalMax:=Prev.Sum;
      If Max .Sum>TotalMax Then TotalMax:=Max .Sum;
      If Last.Sum>TotalMax Then TotalMax:=Last.Sum;
      Prev:=Last;
   End;
   WriteLn(TotalMax);
End;

Var Loop, Interval:LongInt;
    Test:Boolean;
Begin
  MaxId:=NumberOfNodes;
  Interval := Size Div MaxId;
  Test :=True;                // Flaga
  If Interval<10 Then Begin   // Czy oplaca sie wysylac do instancji
     Interval:=Size;          // Ustaw zakres
     Test:=False;             // Zmien
     MaxId:=0;
  End;
  If MyNodeId=0 Then Begin
     If Test And (MaxId>1)Then Begin
        For Loop:=0 to MaxId-2 do Begin
           PutInt( Loop, 1+Loop*Interval );
           PutInt( Loop, Loop*Interval + Interval);
           Send  ( Loop );
        End;
        Loop:=Loop+1;
        PutInt( Loop, 1+Loop*Interval);
        PutInt( Loop, Size           );
        Send  ( Loop                 );
     End Else Begin
          PutInt( 1, 1              );
          PutInt( 1, Size           );
          Send  ( 1                 );
     End;
//     FindMax;
     PrintMax;
  End Else Begin
     FindMax;
  End;
//  ReadLn;
End.