#include <algorithm>
#include <cstdio>
#include <vector>
#include "skup.h"
#include "message.h"
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define VAR(v,w) __typeof(w) v=(w)
#define FORE(it,c) for(VAR(it,(c).begin());it!=(c).end();++it)
#define PB push_back
#define ALL(c) (c).begin(),(c).end()
#define SIZE(c) ((int)(c).size())
typedef long long LL;
typedef vector<int> VI;
typedef vector<bool> VB;
int nodes, node;
VI blocks[100];
bool have[100];
int already;
VB share(int id) {
LL m1 = 0, m2 = 0;
if (id >= 0) {
if (id >= 50) m2 = 1LL << (id - 50);
else m1 = 1LL << id;
}
REP(i,nodes-1) {
REP(j,nodes) if (j != node) {
PutLL(j, m1);
PutLL(j, m2);
Send(j);
}
REP(j,nodes) if (j != node) {
Receive(j);
m1 |= GetLL(j);
m2 |= GetLL(j);
}
}
VB shared(nodes);
REP(i,min(nodes,50)) shared[i] = (m1 >> i) & 1;
FOR(i,50,nodes) shared[i] = (m2 >> (i - 50)) & 1;
return shared;
}
void sendBlock(int t, int f) {
PutInt(t, f + 1);
PutInt(t, SIZE(blocks[f]));
REP(i,1000) PutInt(t, i < SIZE(blocks[f]) ? blocks[f][i] : 0);
Send(t);
}
int getBlock() {
int s = Receive(-1);
int f = GetInt(s) - 1;
int size = GetInt(s);
VI block(1000);
REP(i,1000) block[i] = GetInt(s);
if (f < 0 || have[f]) return -1;
block.resize(size);
swap(block, blocks[f]);
have[f] = 1;
++already;
return f;
}
int main() {
nodes = NumberOfNodes();
node = MyNodeId();
bool master = 0;
VB visible = share(node);
int known = count(ALL(visible), true);
if (known == nodes) {
VB seers = share(node);
if (find(ALL(seers), true) - seers.begin() == node) master = 1;
} else share(-1);
int n = NumberOfCompanies();
blocks[node].resize(n);
REP(i,n) blocks[node][i] = GetShareCost(i);
have[node] = 1;
already = 1;
REP(i,nodes) if (i != node) sendBlock(i, node);
while (already < known) {
int f = getBlock();
if (f >= 0) REP(i,nodes) if (i != node) sendBlock(i, f);
}
if (!master) return 0;
VI c;
REP(i,nodes) FORE(it,blocks[i]) c.PB(*it);
sort(ALL(c));
int cc = SIZE(c);
LL res = 0;
REP(i,cc) res += LL(cc - i) * c[i];
printf("%lld\n", res);
}
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 | #include <algorithm> #include <cstdio> #include <vector> #include "skup.h" #include "message.h" using namespace std; #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define REP(i,n) FOR(i,0,n) #define VAR(v,w) __typeof(w) v=(w) #define FORE(it,c) for(VAR(it,(c).begin());it!=(c).end();++it) #define PB push_back #define ALL(c) (c).begin(),(c).end() #define SIZE(c) ((int)(c).size()) typedef long long LL; typedef vector<int> VI; typedef vector<bool> VB; int nodes, node; VI blocks[100]; bool have[100]; int already; VB share(int id) { LL m1 = 0, m2 = 0; if (id >= 0) { if (id >= 50) m2 = 1LL << (id - 50); else m1 = 1LL << id; } REP(i,nodes-1) { REP(j,nodes) if (j != node) { PutLL(j, m1); PutLL(j, m2); Send(j); } REP(j,nodes) if (j != node) { Receive(j); m1 |= GetLL(j); m2 |= GetLL(j); } } VB shared(nodes); REP(i,min(nodes,50)) shared[i] = (m1 >> i) & 1; FOR(i,50,nodes) shared[i] = (m2 >> (i - 50)) & 1; return shared; } void sendBlock(int t, int f) { PutInt(t, f + 1); PutInt(t, SIZE(blocks[f])); REP(i,1000) PutInt(t, i < SIZE(blocks[f]) ? blocks[f][i] : 0); Send(t); } int getBlock() { int s = Receive(-1); int f = GetInt(s) - 1; int size = GetInt(s); VI block(1000); REP(i,1000) block[i] = GetInt(s); if (f < 0 || have[f]) return -1; block.resize(size); swap(block, blocks[f]); have[f] = 1; ++already; return f; } int main() { nodes = NumberOfNodes(); node = MyNodeId(); bool master = 0; VB visible = share(node); int known = count(ALL(visible), true); if (known == nodes) { VB seers = share(node); if (find(ALL(seers), true) - seers.begin() == node) master = 1; } else share(-1); int n = NumberOfCompanies(); blocks[node].resize(n); REP(i,n) blocks[node][i] = GetShareCost(i); have[node] = 1; already = 1; REP(i,nodes) if (i != node) sendBlock(i, node); while (already < known) { int f = getBlock(); if (f >= 0) REP(i,nodes) if (i != node) sendBlock(i, f); } if (!master) return 0; VI c; REP(i,nodes) FORE(it,blocks[i]) c.PB(*it); sort(ALL(c)); int cc = SIZE(c); LL res = 0; REP(i,cc) res += LL(cc - i) * c[i]; printf("%lld\n", res); } |
English