#include "message.h" #include "teatr.h" #include <iostream> #include <vector> using namespace std; typedef long long ll; // ceiling a/n int ceil_div(int a, int n) { return (a % n == 0) ? (a / n) : (a / n) + 1; } ll count_inversions_naive(vector<ll> &elements) { // O(n) dla 1 do 5 // O(n^2) --> n log n dla dużego ll inv = 0; vector<ll> counts = vector<ll>(6, 0); for (int i = 0; i < elements.size(); ++i) { int digit = elements[i]; for (int d = digit + 1; d < counts.size(); ++d) { inv += counts[d]; } counts[digit]++; } return inv; } ll calculate_inversions_on_counts(vector<ll> &left, vector<ll> &right) { // left.size() jest równe right.size() bo to liczby cyfr, uwaga pole [0] to inv ll inv = 0; for (int r = 1; r < right.size() - 1; ++r) { ll greater = 0; for (int l = r + 1; l < left.size(); ++l) { greater += left[l]; } inv += greater * right[r]; } return inv; } // counts nums and inversions vector<ll> count_nums_and_invs_naive(int beg, int end) { vector<ll> elements = vector<ll>(end - beg + 1); vector<ll> counts = vector<ll>(6, 0); for (int i = beg; i <= end; ++i) { int element = GetElement(i); elements[i - beg] = element; counts[element]++; } counts[0] = count_inversions_naive(elements); return counts; } // sends counts and number of inversions void send_counts(int target, vector<ll> &counts) { PutLL(target, counts.size()); for (int i = 0; i < counts.size(); ++i) { PutLL(target, counts[i]); } Send(target); } vector<ll> receive_counts(int source) { Receive(source); int size = GetLL(source); vector<ll> counts = vector<ll>(size); for (int i = 0; i < size; ++i) { counts[i] = GetLL(source); } return counts; } // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI int main() { // if get n < nodes_num to licz w jednej instancji (nr 0) int id = MyNodeId(); int nodes_num = NumberOfNodes(); int n = GetN(); if (id >= n) { return 0; } if (n < nodes_num) { nodes_num = n; } int length = ceil_div(n, nodes_num); nodes_num = ceil_div(n, length); if (id >= nodes_num) { return 0; } int beg = id * length; int end = (beg + length - 1 < n) ? beg + length - 1 : n - 1; if (beg > end) { return 0; } //cout << "beg " << beg << " end " << end << endl; vector<ll> my_counts = count_nums_and_invs_naive(beg, end); //cout << "test1" << endl; // first round - sending if (id % 2 == 1) { // nieparzyste id wysyłają do parzystych send_counts(id - 1, my_counts); } // len -- na pocz pętli aktualne długości większości bloków (ew. poza ostatnim) <- bzdura, długość bloków, ale w node'ach for (int len = 1; len < nodes_num; len *= 2) { if (id % (len * 2) == 0) { int brother_id = id + len; if (brother_id < nodes_num) { // posiadam brata vector<ll> right_counts = receive_counts(brother_id); // [0] = inv, [i] = count i my_counts[0] += calculate_inversions_on_counts(my_counts, right_counts); for (int i = 0; i < my_counts.size(); ++i) { my_counts[i] += right_counts[i]; } } if (id != 0 && id % (len * 4) != 0) { // jeśli nie będę ojcem, prześlij wynik ojcowi send_counts(id - (id % (len * 4)), my_counts); } } } if (id == 0) { cout << my_counts[0] << 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #include "message.h" #include "teatr.h" #include <iostream> #include <vector> using namespace std; typedef long long ll; // ceiling a/n int ceil_div(int a, int n) { return (a % n == 0) ? (a / n) : (a / n) + 1; } ll count_inversions_naive(vector<ll> &elements) { // O(n) dla 1 do 5 // O(n^2) --> n log n dla dużego ll inv = 0; vector<ll> counts = vector<ll>(6, 0); for (int i = 0; i < elements.size(); ++i) { int digit = elements[i]; for (int d = digit + 1; d < counts.size(); ++d) { inv += counts[d]; } counts[digit]++; } return inv; } ll calculate_inversions_on_counts(vector<ll> &left, vector<ll> &right) { // left.size() jest równe right.size() bo to liczby cyfr, uwaga pole [0] to inv ll inv = 0; for (int r = 1; r < right.size() - 1; ++r) { ll greater = 0; for (int l = r + 1; l < left.size(); ++l) { greater += left[l]; } inv += greater * right[r]; } return inv; } // counts nums and inversions vector<ll> count_nums_and_invs_naive(int beg, int end) { vector<ll> elements = vector<ll>(end - beg + 1); vector<ll> counts = vector<ll>(6, 0); for (int i = beg; i <= end; ++i) { int element = GetElement(i); elements[i - beg] = element; counts[element]++; } counts[0] = count_inversions_naive(elements); return counts; } // sends counts and number of inversions void send_counts(int target, vector<ll> &counts) { PutLL(target, counts.size()); for (int i = 0; i < counts.size(); ++i) { PutLL(target, counts[i]); } Send(target); } vector<ll> receive_counts(int source) { Receive(source); int size = GetLL(source); vector<ll> counts = vector<ll>(size); for (int i = 0; i < size; ++i) { counts[i] = GetLL(source); } return counts; } // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI // ZAMIENIĆ WEKTORY NA LONG LONGI int main() { // if get n < nodes_num to licz w jednej instancji (nr 0) int id = MyNodeId(); int nodes_num = NumberOfNodes(); int n = GetN(); if (id >= n) { return 0; } if (n < nodes_num) { nodes_num = n; } int length = ceil_div(n, nodes_num); nodes_num = ceil_div(n, length); if (id >= nodes_num) { return 0; } int beg = id * length; int end = (beg + length - 1 < n) ? beg + length - 1 : n - 1; if (beg > end) { return 0; } //cout << "beg " << beg << " end " << end << endl; vector<ll> my_counts = count_nums_and_invs_naive(beg, end); //cout << "test1" << endl; // first round - sending if (id % 2 == 1) { // nieparzyste id wysyłają do parzystych send_counts(id - 1, my_counts); } // len -- na pocz pętli aktualne długości większości bloków (ew. poza ostatnim) <- bzdura, długość bloków, ale w node'ach for (int len = 1; len < nodes_num; len *= 2) { if (id % (len * 2) == 0) { int brother_id = id + len; if (brother_id < nodes_num) { // posiadam brata vector<ll> right_counts = receive_counts(brother_id); // [0] = inv, [i] = count i my_counts[0] += calculate_inversions_on_counts(my_counts, right_counts); for (int i = 0; i < my_counts.size(); ++i) { my_counts[i] += right_counts[i]; } } if (id != 0 && id % (len * 4) != 0) { // jeśli nie będę ojcem, prześlij wynik ojcowi send_counts(id - (id % (len * 4)), my_counts); } } } if (id == 0) { cout << my_counts[0] << endl; } return 0; } |