#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include "message.h" #include "krazki.h" using namespace std; int kompy, ID, poczatek, koniec, n, m, result, wynik, pozycja, roznica, licznik, gdzie, IDn, IDm; int poczatekN, koniecN, poczatekM, koniecM; long long dysk, najmniejszy, najwiekszy; long long tab[20000999]; long long minima[105]; long long maksima[105]; int minPoz[105]; int maxPoz[105]; long long MAX; vector < pair <int, int> > zapytania[105]; int main () { MAX = 1000000000000000005; n = PipeHeight(); m = NumberOfDiscs(); kompy = NumberOfNodes(); ID = MyNodeId(); if (m > n) { if (ID == 0) printf("0\n"); return 0; } if (n <= 100000) { if (ID == 0) { for (int i = 1; i <= n; ++i) tab[i] = HoleDiameter(i); for (int i = 2; i <= n; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; result = n + 1; for (int i = 1; i <= m; ++i) { dysk = DiscDiameter(i); result--; if (result == 0) break; while (dysk > tab[result]) { result--; if (result == 0) break; } if (result == 0) break; } printf("%d\n", result); } return 0; } poczatek = (n / kompy) * ID; koniec = (n / kompy) * (ID + 1); if (ID == kompy - 1) koniec = n + 1; najmniejszy = MAX; for (int i = poczatek; i < koniec; ++i) { if (i != 0) dysk = HoleDiameter(i); else dysk = MAX; if (dysk < najmniejszy) najmniejszy = dysk; } PutLL(0, najmniejszy); poczatek = (m / kompy) * ID; koniec = (m / kompy) * (ID + 1); if (ID == kompy - 1) koniec = m + 1; najwiekszy = 0; for (int i = poczatek; i < koniec; ++i) { if (i != 0) dysk = DiscDiameter(i); else dysk = 0; if (dysk > najwiekszy) najwiekszy = dysk; } PutLL(0, najwiekszy); Send(0); if (ID == 0) { for (int i = 0; i < kompy; ++i) { Receive(i); minima[i] = GetLL(i); maksima[i] = GetLL(i); } for (int i = 1; i < kompy; ++i) if (minima[i] > minima[i - 1]) minima[i] = minima[i - 1]; for (int i = 1; i < kompy; ++i) if (maksima[i] < maksima[i - 1]) maksima[i] = maksima[i - 1]; } result = 1000000000; if (m <= 100000) { if (ID == 0) { PutLL(0, MAX); for (int i = 1; i < kompy; ++i) PutLL(i, minima[i - 1]); for (int i = 0; i < kompy; ++i) Send(i); } Receive(0); najmniejszy = GetLL(0); poczatek = (n / kompy) * ID; koniec = (n / kompy) * (ID + 1); if (ID == kompy - 1) koniec = n + 1; roznica = koniec - poczatek; for (int i = poczatek; i < koniec; ++i) { if (i != 0) tab[i - poczatek] = HoleDiameter(i); else tab[i] = MAX; } if (najmniejszy < tab[0]) tab[0] = najmniejszy; for (int i = 1; i < roznica; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; if (ID == kompy - 1) tab[roznica] = 0; else tab[roznica] = min(HoleDiameter(koniec), tab[roznica - 1]); pozycja = roznica; najwiekszy = 0; for (int i = 1; i <= m; ++i) { dysk = DiscDiameter(i); if (dysk > najwiekszy) najwiekszy = dysk; while (najwiekszy > tab[pozycja]) { pozycja--; if (pozycja == -1) break; } if (pozycja == -1) break; if (pozycja == roznica) continue; if (pozycja + poczatek + i - m < result) result = pozycja + poczatek + i - m; } PutInt(0, result); Send(0); if (ID == 0) { wynik = 1000000005; for (int i = 0; i < kompy; ++i) { Receive(i); result = GetInt(i); if (result < wynik) wynik = result; } if (wynik < 0) wynik = 0; printf("%d\n", wynik); } return 0; } if (ID == 0) { gdzie = 0; licznik = kompy - 1; for (int i = 0; i < kompy; ++i) { zapytania[gdzie].push_back(make_pair(i, licznik)); gdzie = (gdzie + 1) % kompy; if (licznik == 0) continue; while (minima[licznik] < maksima[i]) { licznik--; zapytania[gdzie].push_back(make_pair(i, licznik)); gdzie = (gdzie + 1) % kompy; if (licznik == 0) break; } } for (int i = 0; i < kompy; ++i) { PutInt(i, zapytania[i].size()); for (int j = 0; j < zapytania[i].size(); ++j) { int MM = zapytania[i][j].first; int NN = zapytania[i][j].second; PutInt(i, MM); PutInt(i, NN); if (MM == 0) PutLL(i, 0); else PutLL(i, maksima[MM - 1]); if (NN == 0) PutLL(i, MAX); else PutLL(i, minima[NN - 1]); } Send(i); } } Receive(0); int liczba = GetInt(0); result = 1000000000; for (int i = 0; i < liczba; ++i) { IDm = GetInt(0); IDn = GetInt(0); najwiekszy = GetLL(0); najmniejszy = GetLL(0); poczatek = (n / kompy) * IDn; koniec = (n / kompy) * (IDn + 1); if (IDn == kompy - 1) koniec = n + 1; roznica = koniec - poczatek; for (int i = poczatek; i < koniec; ++i) { if (i != 0) tab[i - poczatek] = HoleDiameter(i); else tab[i] = MAX; } if (najmniejszy < tab[0]) tab[0] = najmniejszy; for (int i = 1; i < roznica; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; if (IDn == kompy - 1) tab[roznica] = 0; else tab[roznica] = min(HoleDiameter(koniec), tab[roznica - 1]); pozycja = roznica; poczatekM = (m / kompy) * IDm; koniecM = (m / kompy) * (IDm + 1); if (IDm == kompy - 1) koniecM = m + 1; if (IDm == 0) poczatekM = 1; koniecM--; for (int i = poczatekM; i <= koniecM; ++i) { dysk = DiscDiameter(i); if (dysk > najwiekszy) najwiekszy = dysk; while (najwiekszy > tab[pozycja]) { pozycja--; if (pozycja == -1) break; } if (pozycja == -1) break; if (pozycja == roznica) continue; if (pozycja + poczatek + i - m < result) result = pozycja + poczatek + i - m; } } PutInt(0, result); Send(0); if (ID == 0) { wynik = 1000000005; for (int i = 0; i < kompy; ++i) { Receive(i); result = GetInt(i); if (result < wynik) wynik = result; } if (wynik < 0) wynik = 0; printf("%d\n", wynik); } 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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | #include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include "message.h" #include "krazki.h" using namespace std; int kompy, ID, poczatek, koniec, n, m, result, wynik, pozycja, roznica, licznik, gdzie, IDn, IDm; int poczatekN, koniecN, poczatekM, koniecM; long long dysk, najmniejszy, najwiekszy; long long tab[20000999]; long long minima[105]; long long maksima[105]; int minPoz[105]; int maxPoz[105]; long long MAX; vector < pair <int, int> > zapytania[105]; int main () { MAX = 1000000000000000005; n = PipeHeight(); m = NumberOfDiscs(); kompy = NumberOfNodes(); ID = MyNodeId(); if (m > n) { if (ID == 0) printf("0\n"); return 0; } if (n <= 100000) { if (ID == 0) { for (int i = 1; i <= n; ++i) tab[i] = HoleDiameter(i); for (int i = 2; i <= n; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; result = n + 1; for (int i = 1; i <= m; ++i) { dysk = DiscDiameter(i); result--; if (result == 0) break; while (dysk > tab[result]) { result--; if (result == 0) break; } if (result == 0) break; } printf("%d\n", result); } return 0; } poczatek = (n / kompy) * ID; koniec = (n / kompy) * (ID + 1); if (ID == kompy - 1) koniec = n + 1; najmniejszy = MAX; for (int i = poczatek; i < koniec; ++i) { if (i != 0) dysk = HoleDiameter(i); else dysk = MAX; if (dysk < najmniejszy) najmniejszy = dysk; } PutLL(0, najmniejszy); poczatek = (m / kompy) * ID; koniec = (m / kompy) * (ID + 1); if (ID == kompy - 1) koniec = m + 1; najwiekszy = 0; for (int i = poczatek; i < koniec; ++i) { if (i != 0) dysk = DiscDiameter(i); else dysk = 0; if (dysk > najwiekszy) najwiekszy = dysk; } PutLL(0, najwiekszy); Send(0); if (ID == 0) { for (int i = 0; i < kompy; ++i) { Receive(i); minima[i] = GetLL(i); maksima[i] = GetLL(i); } for (int i = 1; i < kompy; ++i) if (minima[i] > minima[i - 1]) minima[i] = minima[i - 1]; for (int i = 1; i < kompy; ++i) if (maksima[i] < maksima[i - 1]) maksima[i] = maksima[i - 1]; } result = 1000000000; if (m <= 100000) { if (ID == 0) { PutLL(0, MAX); for (int i = 1; i < kompy; ++i) PutLL(i, minima[i - 1]); for (int i = 0; i < kompy; ++i) Send(i); } Receive(0); najmniejszy = GetLL(0); poczatek = (n / kompy) * ID; koniec = (n / kompy) * (ID + 1); if (ID == kompy - 1) koniec = n + 1; roznica = koniec - poczatek; for (int i = poczatek; i < koniec; ++i) { if (i != 0) tab[i - poczatek] = HoleDiameter(i); else tab[i] = MAX; } if (najmniejszy < tab[0]) tab[0] = najmniejszy; for (int i = 1; i < roznica; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; if (ID == kompy - 1) tab[roznica] = 0; else tab[roznica] = min(HoleDiameter(koniec), tab[roznica - 1]); pozycja = roznica; najwiekszy = 0; for (int i = 1; i <= m; ++i) { dysk = DiscDiameter(i); if (dysk > najwiekszy) najwiekszy = dysk; while (najwiekszy > tab[pozycja]) { pozycja--; if (pozycja == -1) break; } if (pozycja == -1) break; if (pozycja == roznica) continue; if (pozycja + poczatek + i - m < result) result = pozycja + poczatek + i - m; } PutInt(0, result); Send(0); if (ID == 0) { wynik = 1000000005; for (int i = 0; i < kompy; ++i) { Receive(i); result = GetInt(i); if (result < wynik) wynik = result; } if (wynik < 0) wynik = 0; printf("%d\n", wynik); } return 0; } if (ID == 0) { gdzie = 0; licznik = kompy - 1; for (int i = 0; i < kompy; ++i) { zapytania[gdzie].push_back(make_pair(i, licznik)); gdzie = (gdzie + 1) % kompy; if (licznik == 0) continue; while (minima[licznik] < maksima[i]) { licznik--; zapytania[gdzie].push_back(make_pair(i, licznik)); gdzie = (gdzie + 1) % kompy; if (licznik == 0) break; } } for (int i = 0; i < kompy; ++i) { PutInt(i, zapytania[i].size()); for (int j = 0; j < zapytania[i].size(); ++j) { int MM = zapytania[i][j].first; int NN = zapytania[i][j].second; PutInt(i, MM); PutInt(i, NN); if (MM == 0) PutLL(i, 0); else PutLL(i, maksima[MM - 1]); if (NN == 0) PutLL(i, MAX); else PutLL(i, minima[NN - 1]); } Send(i); } } Receive(0); int liczba = GetInt(0); result = 1000000000; for (int i = 0; i < liczba; ++i) { IDm = GetInt(0); IDn = GetInt(0); najwiekszy = GetLL(0); najmniejszy = GetLL(0); poczatek = (n / kompy) * IDn; koniec = (n / kompy) * (IDn + 1); if (IDn == kompy - 1) koniec = n + 1; roznica = koniec - poczatek; for (int i = poczatek; i < koniec; ++i) { if (i != 0) tab[i - poczatek] = HoleDiameter(i); else tab[i] = MAX; } if (najmniejszy < tab[0]) tab[0] = najmniejszy; for (int i = 1; i < roznica; ++i) if (tab[i] > tab[i - 1]) tab[i] = tab[i - 1]; if (IDn == kompy - 1) tab[roznica] = 0; else tab[roznica] = min(HoleDiameter(koniec), tab[roznica - 1]); pozycja = roznica; poczatekM = (m / kompy) * IDm; koniecM = (m / kompy) * (IDm + 1); if (IDm == kompy - 1) koniecM = m + 1; if (IDm == 0) poczatekM = 1; koniecM--; for (int i = poczatekM; i <= koniecM; ++i) { dysk = DiscDiameter(i); if (dysk > najwiekszy) najwiekszy = dysk; while (najwiekszy > tab[pozycja]) { pozycja--; if (pozycja == -1) break; } if (pozycja == -1) break; if (pozycja == roznica) continue; if (pozycja + poczatek + i - m < result) result = pozycja + poczatek + i - m; } } PutInt(0, result); Send(0); if (ID == 0) { wynik = 1000000005; for (int i = 0; i < kompy; ++i) { Receive(i); result = GetInt(i); if (result < wynik) wynik = result; } if (wynik < 0) wynik = 0; printf("%d\n", wynik); } return 0; } |