#include <cstdio> #include <cstdlib> #include <map> #include "message.h" #include "teatr.h" static const int TREE_SIZE = 1024 * 1024; int tree[2 * TREE_SIZE] = {0}; void addToTree(int at) { at += TREE_SIZE; while (at > 0) { tree[at] += 1; at /= 2; } } int treePrefix(int end) { int sum = 0; int pos = 1; int start = 0; int childSize = TREE_SIZE / 2; while (childSize > 0) { if (start + childSize <= end) { sum += tree[2 * pos]; start += childSize; pos = 2 * pos + 1; } else { pos = 2 * pos; } childSize /= 2; } if (start + 1 <= end) { sum += tree[pos]; } return sum; } struct state { std::map<int, int> values; long long int totalInversions; }; void sendStateTo(const int receiver, const state& s) { PutInt(receiver, (int)s.values.size()); PutLL(receiver, s.totalInversions); for (const auto p : s.values) { PutInt(receiver, p.first); PutInt(receiver, p.second); } Send(receiver); } state receiveStateFrom(const int sender) { state ret; Receive(sender); const auto entryCount = GetInt(sender); ret.totalInversions = GetLL(sender); for (int i = 0; i < entryCount; i++) { const auto key = GetInt(sender); const auto value = GetInt(sender); ret.values[key] = value; } return ret; } state scanSector(int begin, int end) { state ret; ret.totalInversions = 0; for (int i = begin; i < end; i++) { const auto el = GetElement(i); const auto visitedSoFar = i - begin; const auto countLargerThan = visitedSoFar - treePrefix(el + 1); ret.totalInversions += countLargerThan; ret.values[el] += 1; addToTree(el); } return ret; } void mergeInState(state& a, const state& b) { auto itB = b.values.begin(); long long int sum = 0; for (const auto& pA : a.values) { while (itB != b.values.end() && itB->first < pA.first) { sum += (long long int)itB->second; ++itB; } a.totalInversions += sum * (long long int)pA.second; } a.totalInversions += b.totalInversions; for (const auto& pB : b.values) { a.values[pB.first] += pB.second; } } int nextPowerOfTwo(int x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x++; return x; } int main() { const int instanceID = MyNodeId(); const int totalInstances = NumberOfNodes(); const int rangeSize = GetN(); const int rangeBegin = (instanceID * rangeSize) / totalInstances; const int rangeEnd = ((instanceID + 1) * rangeSize) / totalInstances; auto currState = scanSector(rangeBegin, rangeEnd); // printf("(%d) Local inversions: %lld\n", instanceID, currState.totalInversions); const int signature = nextPowerOfTwo(totalInstances) + instanceID; int i = 0; for (; !(signature & (1 << i)); i++) { if (instanceID + (1 << i) < totalInstances) { // printf("(%d) Receiving from %d\n", instanceID, instanceID + (1 << i)); const auto otherState = receiveStateFrom(instanceID + (1 << i)); mergeInState(currState, otherState); } } if (instanceID == 0) { printf("%lld\n", currState.totalInversions); } else { // printf("(%d) Sending to %d\n", instanceID, instanceID - (1 << i)); sendStateTo(instanceID - (1 << i), currState); } 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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #include <cstdio> #include <cstdlib> #include <map> #include "message.h" #include "teatr.h" static const int TREE_SIZE = 1024 * 1024; int tree[2 * TREE_SIZE] = {0}; void addToTree(int at) { at += TREE_SIZE; while (at > 0) { tree[at] += 1; at /= 2; } } int treePrefix(int end) { int sum = 0; int pos = 1; int start = 0; int childSize = TREE_SIZE / 2; while (childSize > 0) { if (start + childSize <= end) { sum += tree[2 * pos]; start += childSize; pos = 2 * pos + 1; } else { pos = 2 * pos; } childSize /= 2; } if (start + 1 <= end) { sum += tree[pos]; } return sum; } struct state { std::map<int, int> values; long long int totalInversions; }; void sendStateTo(const int receiver, const state& s) { PutInt(receiver, (int)s.values.size()); PutLL(receiver, s.totalInversions); for (const auto p : s.values) { PutInt(receiver, p.first); PutInt(receiver, p.second); } Send(receiver); } state receiveStateFrom(const int sender) { state ret; Receive(sender); const auto entryCount = GetInt(sender); ret.totalInversions = GetLL(sender); for (int i = 0; i < entryCount; i++) { const auto key = GetInt(sender); const auto value = GetInt(sender); ret.values[key] = value; } return ret; } state scanSector(int begin, int end) { state ret; ret.totalInversions = 0; for (int i = begin; i < end; i++) { const auto el = GetElement(i); const auto visitedSoFar = i - begin; const auto countLargerThan = visitedSoFar - treePrefix(el + 1); ret.totalInversions += countLargerThan; ret.values[el] += 1; addToTree(el); } return ret; } void mergeInState(state& a, const state& b) { auto itB = b.values.begin(); long long int sum = 0; for (const auto& pA : a.values) { while (itB != b.values.end() && itB->first < pA.first) { sum += (long long int)itB->second; ++itB; } a.totalInversions += sum * (long long int)pA.second; } a.totalInversions += b.totalInversions; for (const auto& pB : b.values) { a.values[pB.first] += pB.second; } } int nextPowerOfTwo(int x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x++; return x; } int main() { const int instanceID = MyNodeId(); const int totalInstances = NumberOfNodes(); const int rangeSize = GetN(); const int rangeBegin = (instanceID * rangeSize) / totalInstances; const int rangeEnd = ((instanceID + 1) * rangeSize) / totalInstances; auto currState = scanSector(rangeBegin, rangeEnd); // printf("(%d) Local inversions: %lld\n", instanceID, currState.totalInversions); const int signature = nextPowerOfTwo(totalInstances) + instanceID; int i = 0; for (; !(signature & (1 << i)); i++) { if (instanceID + (1 << i) < totalInstances) { // printf("(%d) Receiving from %d\n", instanceID, instanceID + (1 << i)); const auto otherState = receiveStateFrom(instanceID + (1 << i)); mergeInState(currState, otherState); } } if (instanceID == 0) { printf("%lld\n", currState.totalInversions); } else { // printf("(%d) Sending to %d\n", instanceID, instanceID - (1 << i)); sendStateTo(instanceID - (1 << i), currState); } return 0; } |