#include "message.h"
#include "teatr.h"
#include <bits/stdc++.h>
#define FOR(i, n) for(int i = 0; i < (n); ++i)
#define REP(i, a, b) for(int i = (a); i < (b); ++i)
#define TRAV(i, a) for(auto &i : a)
#define SZ(i) ((int)(i).size())
#define X first
#define Y second
#define PR std::pair
#define PII std::pair<int, int>
#define MP std::make_pair
#define ll long long
#define VI std::vector<int>
#define LSB(i) ((i) & -(i))
const int MAXH = 1000000;
struct BIT{
std::vector<int> tab;
BIT(int size){
tab.resize(size);
}
int sum(int i){
int sum = 0;
while (i > 0)
sum += tab[i], i -= LSB(i);
return sum;
}
void add(int i, int k){
while (i < SZ(tab))
tab[i] += k, i += LSB(i);
}
};
ll count_inversions(const VI &vec){
ll ret = 0;
BIT bit(MAXH+1);
TRAV(a, vec){
ret += bit.sum(MAXH)-bit.sum(a);
bit.add(a, 1);
}
return ret;
}
ll count_inversions_big(VI &lsum, VI &rpref){
ll ret = 0;
REP(i, 1, MAXH+1){
ret += 1ll*lsum[i]*rpref[i-1];
}
return ret;
}
void add_sum(int a, int b, VI &sum){
REP(i, a, b+1) sum[GetElement(i)]++;
}
void get_sum_pref(int a, int b, VI &sum, VI &pref){
std::fill(sum.begin(), sum.end(), 0);
REP(i, a, b+1) sum[GetElement(i)]++;
pref[0] = 0;
REP(i, 1, MAXH+1) pref[i] = pref[i-1] + sum[i];
}
ll ans;
int n, NODES, ME;
std::vector<PII> przedz;
VI small;
VI lsum, lpref, rsum, rpref, allsum, nlsum;
int main() {
n = GetN();
NODES = NumberOfNodes();
ME = MyNodeId();
if(n <= 1000000){
if(ME != 0) return 0;
VI A(n);
FOR(i, n) A[i] = GetElement(i);
std::printf("%lld", count_inversions(A));
return 0;
}
int place = 0;
FOR(i, NODES){
int upto = (i < NODES-1 ? place+n/NODES : n);
przedz.push_back(MP(place, upto-1));
place = upto;
}
int mywork = przedz[ME].Y-przedz[ME].X+1;
small.resize(mywork);
FOR(i, mywork) small[i] = GetElement(przedz[ME].X+i);
ans += count_inversions(small);
// works only for NODES = 100
int which = (ME%10)*10;
lsum.resize(MAXH+1);
add_sum(przedz[which].X, przedz[which].Y, lsum);
rsum.resize(MAXH+1);
rpref.resize(MAXH+1);
REP(i, 1, 10){
get_sum_pref(przedz[which+i].X, przedz[which+i].Y, rsum, rpref);
if(ME < 10) ans += count_inversions_big(lsum, rpref);
FOR(j, MAXH+1) lsum[j] += rsum[j];
}
lpref.resize(MAXH+1);
REP(i, 1, MAXH+1) lpref[i] = lpref[i-1] + lsum[i];
nlsum.resize(MAXH+1);
while(which > 0){
which -= 10;
std::fill(nlsum.begin(), nlsum.end(), 0);
add_sum(przedz[which+ME/10].X, przedz[which+ME/10].Y, nlsum);
ans += count_inversions_big(nlsum, lpref);
}
if(ME == 0){
REP(i, 1, NODES){
Receive(i);
ans += GetLL(i);
}
std::printf("%lld", ans);
}else{
PutLL(0, ans);
Send(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 | #include "message.h" #include "teatr.h" #include <bits/stdc++.h> #define FOR(i, n) for(int i = 0; i < (n); ++i) #define REP(i, a, b) for(int i = (a); i < (b); ++i) #define TRAV(i, a) for(auto &i : a) #define SZ(i) ((int)(i).size()) #define X first #define Y second #define PR std::pair #define PII std::pair<int, int> #define MP std::make_pair #define ll long long #define VI std::vector<int> #define LSB(i) ((i) & -(i)) const int MAXH = 1000000; struct BIT{ std::vector<int> tab; BIT(int size){ tab.resize(size); } int sum(int i){ int sum = 0; while (i > 0) sum += tab[i], i -= LSB(i); return sum; } void add(int i, int k){ while (i < SZ(tab)) tab[i] += k, i += LSB(i); } }; ll count_inversions(const VI &vec){ ll ret = 0; BIT bit(MAXH+1); TRAV(a, vec){ ret += bit.sum(MAXH)-bit.sum(a); bit.add(a, 1); } return ret; } ll count_inversions_big(VI &lsum, VI &rpref){ ll ret = 0; REP(i, 1, MAXH+1){ ret += 1ll*lsum[i]*rpref[i-1]; } return ret; } void add_sum(int a, int b, VI &sum){ REP(i, a, b+1) sum[GetElement(i)]++; } void get_sum_pref(int a, int b, VI &sum, VI &pref){ std::fill(sum.begin(), sum.end(), 0); REP(i, a, b+1) sum[GetElement(i)]++; pref[0] = 0; REP(i, 1, MAXH+1) pref[i] = pref[i-1] + sum[i]; } ll ans; int n, NODES, ME; std::vector<PII> przedz; VI small; VI lsum, lpref, rsum, rpref, allsum, nlsum; int main() { n = GetN(); NODES = NumberOfNodes(); ME = MyNodeId(); if(n <= 1000000){ if(ME != 0) return 0; VI A(n); FOR(i, n) A[i] = GetElement(i); std::printf("%lld", count_inversions(A)); return 0; } int place = 0; FOR(i, NODES){ int upto = (i < NODES-1 ? place+n/NODES : n); przedz.push_back(MP(place, upto-1)); place = upto; } int mywork = przedz[ME].Y-przedz[ME].X+1; small.resize(mywork); FOR(i, mywork) small[i] = GetElement(przedz[ME].X+i); ans += count_inversions(small); // works only for NODES = 100 int which = (ME%10)*10; lsum.resize(MAXH+1); add_sum(przedz[which].X, przedz[which].Y, lsum); rsum.resize(MAXH+1); rpref.resize(MAXH+1); REP(i, 1, 10){ get_sum_pref(przedz[which+i].X, przedz[which+i].Y, rsum, rpref); if(ME < 10) ans += count_inversions_big(lsum, rpref); FOR(j, MAXH+1) lsum[j] += rsum[j]; } lpref.resize(MAXH+1); REP(i, 1, MAXH+1) lpref[i] = lpref[i-1] + lsum[i]; nlsum.resize(MAXH+1); while(which > 0){ which -= 10; std::fill(nlsum.begin(), nlsum.end(), 0); add_sum(przedz[which+ME/10].X, przedz[which+ME/10].Y, nlsum); ans += count_inversions_big(nlsum, lpref); } if(ME == 0){ REP(i, 1, NODES){ Receive(i); ans += GetLL(i); } std::printf("%lld", ans); }else{ PutLL(0, ans); Send(0); } } |
English