#include <bits/stdc++.h>
#include "message.h"
#include "teatr.h"
using namespace std;
#define THRREP(msg) clog << "" << MyNodeId() << " " << msg << endl
#define THRPHS(phs) THRREP("Phase " phs " completed")
template <typename T> struct IndexRange {
struct Iterator {
T i;
const T& operator*() const { return i; }
Iterator& operator++() { ++i; return *this; }
friend bool operator!=(const Iterator& a, const Iterator& b) { return a.i != b.i; }
};
T left, right;
Iterator begin() const { return Iterator{left}; }
Iterator end() const { return Iterator{right}; }
bool empty() const { return left == right; }
};
template <typename T, typename U, typename V> IndexRange<T> workloadRange(T n) {
return IndexRange<V>{(V)((U)MyNodeId()*n/NumberOfNodes()), (V)((U)(MyNodeId()+1)*n/NumberOfNodes())};
}
template <typename T> struct BinaryTreeReporter {
BinaryTreeReporter(){}
void send(T x) {
r = move(x);
auto v = MyNodeId()+1;
if (2*v <= NumberOfNodes())
r = T::merge(r, wrecv(2*v-1));
if (2*v+1 <= NumberOfNodes())
r = T::merge(r, wrecv(2*v+1-1));
if (v != 1)
wsend(v/2-1, r);
}
bool isRoot() {
return MyNodeId() == 0;
}
const T& receive() {
return r;
}
private:
T wrecv(int w) {
Receive(w);
return T::gcjGet(w);
}
void wsend(int w, const T& x) {
x.gcjPut(w);
Send(w);
}
T r;
};
struct I32SumSegtree {
I32SumSegtree(int n):base(1){
while (base < n) base *= 2;
nodes.resize(base*2, 0);
}
void incLeaf(int i) {
for (auto v=base+i; v>0; v>>=1)
++nodes[v];
}
int sumPrefix(int right) const {
auto r = 0;
for (auto vr=base+right; 1<vr; vr>>=1)
if (vr & 1) r += nodes[--vr];
return r;
}
int base;
vector<int> nodes;
};
const int VALUE_MAX = 1000000;
vector<int> countOnRange(int left, int right) {
auto cnt = vector<int>(VALUE_MAX+1, 0);
for (auto i=left; i<right; ++i)
++cnt[GetElement(i)];
return cnt;
}
template <typename T> vector<T> suffixSum(vector<T> xs) {
for (auto i=(int)xs.size()-2; i>=0; --i)
xs[i] += xs[i+1];
return xs;
}
struct Report {
long long result;
static Report merge(const Report& a, const Report& b) { return Report{a.result + b.result}; }
static Report gcjGet(int w) { return Report{GetLL(w)}; }
void gcjPut(int w) const { PutLL(w, result); }
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
auto workload = workloadRange<int, long long, int>(GetN());
auto counts = countOnRange(0, workload.left);
auto farTall = suffixSum(move(counts));
auto nearTall = I32SumSegtree(VALUE_MAX+2);
auto result = 0ll;
for (auto i : workload) {
auto x = GetElement(i);
if (x < VALUE_MAX)
result += farTall[x+1] + nearTall.sumPrefix(VALUE_MAX-x);
nearTall.incLeaf(VALUE_MAX-x);
}
auto reporter = BinaryTreeReporter<Report>();
reporter.send(Report{result});
if (reporter.isRoot())
cout << reporter.receive().result << '\n';
}
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 | #include <bits/stdc++.h> #include "message.h" #include "teatr.h" using namespace std; #define THRREP(msg) clog << "" << MyNodeId() << " " << msg << endl #define THRPHS(phs) THRREP("Phase " phs " completed") template <typename T> struct IndexRange { struct Iterator { T i; const T& operator*() const { return i; } Iterator& operator++() { ++i; return *this; } friend bool operator!=(const Iterator& a, const Iterator& b) { return a.i != b.i; } }; T left, right; Iterator begin() const { return Iterator{left}; } Iterator end() const { return Iterator{right}; } bool empty() const { return left == right; } }; template <typename T, typename U, typename V> IndexRange<T> workloadRange(T n) { return IndexRange<V>{(V)((U)MyNodeId()*n/NumberOfNodes()), (V)((U)(MyNodeId()+1)*n/NumberOfNodes())}; } template <typename T> struct BinaryTreeReporter { BinaryTreeReporter(){} void send(T x) { r = move(x); auto v = MyNodeId()+1; if (2*v <= NumberOfNodes()) r = T::merge(r, wrecv(2*v-1)); if (2*v+1 <= NumberOfNodes()) r = T::merge(r, wrecv(2*v+1-1)); if (v != 1) wsend(v/2-1, r); } bool isRoot() { return MyNodeId() == 0; } const T& receive() { return r; } private: T wrecv(int w) { Receive(w); return T::gcjGet(w); } void wsend(int w, const T& x) { x.gcjPut(w); Send(w); } T r; }; struct I32SumSegtree { I32SumSegtree(int n):base(1){ while (base < n) base *= 2; nodes.resize(base*2, 0); } void incLeaf(int i) { for (auto v=base+i; v>0; v>>=1) ++nodes[v]; } int sumPrefix(int right) const { auto r = 0; for (auto vr=base+right; 1<vr; vr>>=1) if (vr & 1) r += nodes[--vr]; return r; } int base; vector<int> nodes; }; const int VALUE_MAX = 1000000; vector<int> countOnRange(int left, int right) { auto cnt = vector<int>(VALUE_MAX+1, 0); for (auto i=left; i<right; ++i) ++cnt[GetElement(i)]; return cnt; } template <typename T> vector<T> suffixSum(vector<T> xs) { for (auto i=(int)xs.size()-2; i>=0; --i) xs[i] += xs[i+1]; return xs; } struct Report { long long result; static Report merge(const Report& a, const Report& b) { return Report{a.result + b.result}; } static Report gcjGet(int w) { return Report{GetLL(w)}; } void gcjPut(int w) const { PutLL(w, result); } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); auto workload = workloadRange<int, long long, int>(GetN()); auto counts = countOnRange(0, workload.left); auto farTall = suffixSum(move(counts)); auto nearTall = I32SumSegtree(VALUE_MAX+2); auto result = 0ll; for (auto i : workload) { auto x = GetElement(i); if (x < VALUE_MAX) result += farTall[x+1] + nearTall.sumPrefix(VALUE_MAX-x); nearTall.incLeaf(VALUE_MAX-x); } auto reporter = BinaryTreeReporter<Report>(); reporter.send(Report{result}); if (reporter.isRoot()) cout << reporter.receive().result << '\n'; } |
English