#include <cstdio>
#include <algorithm>
#include <stack>
#include "dzialka.h"
#include "message.h"
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define LL long long
#define PII pair<int, int>
#define MP make_pair
#define FI first
#define SE second
using namespace std;
const int maxlen = 75010;
const int maxnodelen = 760;
const int messageLimit = 990;
int numNodes;
int nodeId;
LL row[maxlen];
char use[maxnodelen][maxlen];
int top[maxlen];
int down[maxlen];
stack<PII> st;
void receiveTop(int from, int to) {
if (nodeId == 0) {
return;
}
Receive(nodeId - 1);
FOR(c, from, to - 1) {
top[c] = GetLL(nodeId - 1);
}
}
void sendDown(int from, int to) {
if (nodeId == numNodes - 1) {
return;
}
FOR(c, from, to - 1) {
PutLL(nodeId + 1, down[c]);
}
Send(nodeId + 1);
}
int main() {
numNodes = NumberOfNodes();
nodeId = MyNodeId();
int maxC = GetFieldWidth();
int maxR = GetFieldHeight();
int nodeRRange = maxR/numNodes + 1;
int fromR = nodeId*nodeRRange;
int toR = min((nodeId + 1)*nodeRRange, maxR);
int colBatch = maxC/messageLimit + 1;
int toC;
for(int fromC = 0; fromC <= maxC - 1; fromC += colBatch) {
toC = min(fromC + colBatch, maxC);
receiveTop(fromC, toC);
FOR(c, fromC, toC - 1) {
down[c] = top[c];
}
FOR(r, fromR, toR - 1) {
FOR(c, fromC, toC - 1) {
use[r - fromR][c] = IsUsableCell(r, c);
if (!use[r - fromR][c]) {
down[c] = r + 1;
}
}
}
sendDown(fromC, toC);
}
int height;
int rectFromC;
LL res = 0;
FOR(r, fromR, toR - 1) {
while (!st.empty()) {
st.pop();
}
FOR(c, 0, maxC - 1) {
if (!use[r - fromR][c]) {
top[c] = r + 1;
}
height = r - top[c] + 1;
rectFromC = c;
while (!st.empty() && st.top().SE > height) {
rectFromC = st.top().FI;
st.pop();
}
if (!st.empty() && st.top().SE == height) {
rectFromC = st.top().FI;
}
row[c] = ((rectFromC == 0) ? 0 : row[rectFromC - 1]) + (LL)height*(LL)(c - rectFromC + 1);
res += row[c];
if (height > 0 && (st.empty() || st.top().SE < height)) {
st.push(MP(rectFromC, height));
}
}
}
if (nodeId == 0) {
FOR(source, 1, numNodes - 1) {
Receive(source);
res += GetLL(source);
}
printf("%lld\n", res);
} else {
PutLL(0, res);
Send(0);
}
return 0;
}
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 | #include <cstdio> #include <algorithm> #include <stack> #include "dzialka.h" #include "message.h" #define REP(i, n) for (int i = 0; i < (n); ++i) #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) #define LL long long #define PII pair<int, int> #define MP make_pair #define FI first #define SE second using namespace std; const int maxlen = 75010; const int maxnodelen = 760; const int messageLimit = 990; int numNodes; int nodeId; LL row[maxlen]; char use[maxnodelen][maxlen]; int top[maxlen]; int down[maxlen]; stack<PII> st; void receiveTop(int from, int to) { if (nodeId == 0) { return; } Receive(nodeId - 1); FOR(c, from, to - 1) { top[c] = GetLL(nodeId - 1); } } void sendDown(int from, int to) { if (nodeId == numNodes - 1) { return; } FOR(c, from, to - 1) { PutLL(nodeId + 1, down[c]); } Send(nodeId + 1); } int main() { numNodes = NumberOfNodes(); nodeId = MyNodeId(); int maxC = GetFieldWidth(); int maxR = GetFieldHeight(); int nodeRRange = maxR/numNodes + 1; int fromR = nodeId*nodeRRange; int toR = min((nodeId + 1)*nodeRRange, maxR); int colBatch = maxC/messageLimit + 1; int toC; for(int fromC = 0; fromC <= maxC - 1; fromC += colBatch) { toC = min(fromC + colBatch, maxC); receiveTop(fromC, toC); FOR(c, fromC, toC - 1) { down[c] = top[c]; } FOR(r, fromR, toR - 1) { FOR(c, fromC, toC - 1) { use[r - fromR][c] = IsUsableCell(r, c); if (!use[r - fromR][c]) { down[c] = r + 1; } } } sendDown(fromC, toC); } int height; int rectFromC; LL res = 0; FOR(r, fromR, toR - 1) { while (!st.empty()) { st.pop(); } FOR(c, 0, maxC - 1) { if (!use[r - fromR][c]) { top[c] = r + 1; } height = r - top[c] + 1; rectFromC = c; while (!st.empty() && st.top().SE > height) { rectFromC = st.top().FI; st.pop(); } if (!st.empty() && st.top().SE == height) { rectFromC = st.top().FI; } row[c] = ((rectFromC == 0) ? 0 : row[rectFromC - 1]) + (LL)height*(LL)(c - rectFromC + 1); res += row[c]; if (height > 0 && (st.empty() || st.top().SE < height)) { st.push(MP(rectFromC, height)); } } } if (nodeId == 0) { FOR(source, 1, numNodes - 1) { Receive(source); res += GetLL(source); } printf("%lld\n", res); } else { PutLL(0, res); Send(0); } return 0; } |
English