#include "dzialka.h" #include "message.h" #include <iostream> #include <vector> #include <stack> #include <cassert> using namespace std; using LL = long long; using STACK = vector<pair<int, int>>; inline void add(LL& s, LL h, LL w) { s += (w * (w + 1) / 2) * h; } STACK st; int sts; inline void reduce_stack(LL& sum, int pos) { assert(sts > 0); auto tp = st[--sts]; if (sts > 0) { add(sum, tp.first - st[sts-1].first, pos - tp.second); } else { add(sum, tp.first, pos); } } int main() { int n = GetFieldHeight(), m = GetFieldWidth(); if (n <= MyNodeId()) { return 0; } int nodes_num = min(n, NumberOfNodes()); int std_chunk_size = n / nodes_num; int my_chunk_size; if (MyNodeId() == nodes_num - 1) { my_chunk_size = n - (nodes_num - 1) * std_chunk_size; } else { my_chunk_size = std_chunk_size; } vector<int> t(m, 0); int beg = std_chunk_size * MyNodeId(); for (int i = beg; i < beg + my_chunk_size; ++i) { for (int j = 0; j < m; ++j) { if (IsUsableCell(i, j)) { t[j] += 1; } else { t[j] = 0; } } } vector<int> s(m); if (MyNodeId() > 0) { int pred = MyNodeId() - 1; Receive(pred); for (int j = 0; j < m; ++j) { s[j] = GetInt(pred); if (t[j] == my_chunk_size) { t[j] += s[j]; } } } if (MyNodeId() < nodes_num - 1) { int succ = MyNodeId() + 1; for (int j = 0; j < m; ++j) { PutInt(succ, t[j]); } Send(succ); } LL sum = 0; st.resize(m + 1); for (int i = beg; i < beg + my_chunk_size; ++i) { for (int j = 0; j < m; ++j) { if (IsUsableCell(i, j)) { s[j] += 1; } else { s[j] = 0; } } sts = 1; st[0] = make_pair(0, -1); for (int j = 0; j < m; ++j) { int last = j; while (sts > 0 && st[sts-1].first >= s[j]) { auto tp = st[--sts]; if (sts > 0) { add(sum, min(tp.first - st[sts-1].first, tp.first - s[j]), j - tp.second); } else { add(sum, tp.first, j); } last = tp.second; } st[sts++] = make_pair(s[j], last); } while (sts > 0) { reduce_stack(sum, m); } } if (MyNodeId() > 0) { PutLL(0, sum); Send(0); return 0; } LL sumall = sum; for (int i = 1; i < nodes_num; ++i) { int node = Receive(-1); sumall += GetLL(node); } cout << sumall << endl; 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 "dzialka.h" #include "message.h" #include <iostream> #include <vector> #include <stack> #include <cassert> using namespace std; using LL = long long; using STACK = vector<pair<int, int>>; inline void add(LL& s, LL h, LL w) { s += (w * (w + 1) / 2) * h; } STACK st; int sts; inline void reduce_stack(LL& sum, int pos) { assert(sts > 0); auto tp = st[--sts]; if (sts > 0) { add(sum, tp.first - st[sts-1].first, pos - tp.second); } else { add(sum, tp.first, pos); } } int main() { int n = GetFieldHeight(), m = GetFieldWidth(); if (n <= MyNodeId()) { return 0; } int nodes_num = min(n, NumberOfNodes()); int std_chunk_size = n / nodes_num; int my_chunk_size; if (MyNodeId() == nodes_num - 1) { my_chunk_size = n - (nodes_num - 1) * std_chunk_size; } else { my_chunk_size = std_chunk_size; } vector<int> t(m, 0); int beg = std_chunk_size * MyNodeId(); for (int i = beg; i < beg + my_chunk_size; ++i) { for (int j = 0; j < m; ++j) { if (IsUsableCell(i, j)) { t[j] += 1; } else { t[j] = 0; } } } vector<int> s(m); if (MyNodeId() > 0) { int pred = MyNodeId() - 1; Receive(pred); for (int j = 0; j < m; ++j) { s[j] = GetInt(pred); if (t[j] == my_chunk_size) { t[j] += s[j]; } } } if (MyNodeId() < nodes_num - 1) { int succ = MyNodeId() + 1; for (int j = 0; j < m; ++j) { PutInt(succ, t[j]); } Send(succ); } LL sum = 0; st.resize(m + 1); for (int i = beg; i < beg + my_chunk_size; ++i) { for (int j = 0; j < m; ++j) { if (IsUsableCell(i, j)) { s[j] += 1; } else { s[j] = 0; } } sts = 1; st[0] = make_pair(0, -1); for (int j = 0; j < m; ++j) { int last = j; while (sts > 0 && st[sts-1].first >= s[j]) { auto tp = st[--sts]; if (sts > 0) { add(sum, min(tp.first - st[sts-1].first, tp.first - s[j]), j - tp.second); } else { add(sum, tp.first, j); } last = tp.second; } st[sts++] = make_pair(s[j], last); } while (sts > 0) { reduce_stack(sum, m); } } if (MyNodeId() > 0) { PutLL(0, sum); Send(0); return 0; } LL sumall = sum; for (int i = 1; i < nodes_num; ++i) { int node = Receive(-1); sumall += GetLL(node); } cout << sumall << endl; return 0; } |