#include <iostream> #include <algorithm> #include <vector> #include "message.h" #include "palindromy.h" #define debug 0 using namespace std; int id; char Get(int a) { // TODO if (debug) cout << "ask for " << id << " about " << a << endl; return GetLetter(a); } long long add(int a, int prom, bool niep); //From Algorytmika Praktyczna: long long PalRad(int start, int fin, bool niep) { if (debug) cout << "palindromy for " << id << " params: " << start << ", " << fin << ", " << niep << endl; int n = fin - start, i = 1, j = 0, k; vector<int> r(n, 0); //200 MB long long ans = 0; while (i < n) { // while (i + j + niep <= n && i - j > 0 && Get(start + i - j - 1) == Get(start + i + j + niep)) while (i + j + niep < n && i - j > 0 && Get(start + i - j - 1) == Get(start + i + j + niep)) j++; r[i] = j; k = 1; while (r[i - k] != j - k && k <= j) { r[i + k] = min(r[i - k], j - k); ++k; } j = max(0, j - k); i += k; } for (unsigned a = 0; a < r.size(); ++a) { //cout << "xxx " << a + start << " niep = " << niep << ": " << r[a] << ", " << a << ", " << fin - a -niep << endl; if (r[a] == a || r[a] == fin - start - a - niep) { r[a] = add(a, r[a], niep); } ans += r[a]; //cout << "value for " << niep << ", " << a + start << " r = " << r[a] << " by " << id << endl; } return ans; } long long ans; long long p1 = 99194853094755497ll, p2 = 2305843009213693951ll; int n, maxId, k; int start, fin; int step = 1000; inline long long calc_hash(long long h, long long a) { return (h * p1 + a) % p2; } // GetLetter // GetLength vector<long long> prev_all(100), next_all(100); // malo long long my_all_to_r, my_all_to_l; // malo vector<long long> prev_step[100], next_step[100]; // 4 MB vector<long long> my_to_r, my_to_l; // 0.8 MB bool takie_same(int s1, int e1, int s2, int e2) { //return wether [s1, e1) = [s2, e2) //TODO for (int i = s1; i < e1; ++i) { if (Get(i) != Get(i - s1 + s2)) return false; } return true; } bool ok(int a, int s, int prom, bool niep) { // w a jest palindrom niep o promieniu prom. czy jest tez o promieniu s? bool ans = takie_same(a - s, a - prom, a + niep + prom, a + niep + s); //cout << "ok " << a << " with niep = " << niep << " ans = " << ans << endl; return ans; } long long add(int a, int prom, bool niep) { int pos = a + start; //cout << "pos = " << pos << " niep = " << niep << endl; while (pos - prom - 1 >= 0 && pos + prom + niep < n && Get(pos-prom-1) == Get(pos + prom + niep)) ++prom; return prom; /* int end = min(pos + 1, 1 + n - pos - niep); cout << "add by " << id << " with " << pos << ", " << prom << ", " << niep << ". end = " << end << endl; while (prom + 1 < end) { int s = (prom + end)/2; if (ok(pos, s, prom, niep)) prom = s; else end = s; } return prom; */ } void calc_hashes() { //to right int ile = 0; long long h = 0; for (int i = start; i < fin; ++i) { h = calc_hash(h, Get(i)); ++ile; if (ile % step == 0) my_to_r.push_back(h); } my_all_to_r = h; //to left h = 0; ile = 0; for (int i = fin - 1; i >= start; --i) { h = calc_hash(h, Get(i)); ++ile; if (ile % step == 0) my_to_l.push_back(h); } my_all_to_l = h; for (int i = 0; i < id; ++i) { PutLL(i, my_all_to_r); PutInt(i, my_to_r.size()); for (unsigned j = 0; j < my_to_r.size(); ++j) { PutLL(i, my_to_r[j]); } Send(i); } for (int i = id+1; i < maxId; ++i) { PutLL(i, my_all_to_l); PutInt(i, my_to_l.size()); for (unsigned j = 0; j < my_to_l.size(); ++j) { PutLL(i, my_to_l[j]); } Send(i); } for (int i = 1; i < maxId; ++i) { int from = Receive(-1); if (debug) cout << "received for " << id << " from " << from << endl; if (from > id) { // read to next next_all[from] = GetLL(from); int s = GetInt(from); for (int j = 0; j < s; ++j) next_step[from].push_back(GetLL(from)); } else { prev_all[from] = GetLL(from); int s = GetInt(from); for (int j = 0; j < s; ++j) prev_step[from].push_back(GetLL(from)); } } } int main() { n = GetLength(); id = MyNodeId(); maxId = NumberOfNodes(); if (n < maxId) maxId = n; k = n / maxId; start = k * id; fin = start + k; if (id == maxId - 1) fin = n; if (id >= maxId) return 0; calc_hashes(); ans += PalRad(start, fin, 1); ans += PalRad(start, fin, 0); ans += fin - start; if (id > 0) { PutLL(0, ans); Send(0); } else { for (int i = 1; i < maxId; ++i) { int from = Receive(-1); ans += GetLL(from); } cout << ans << endl; } 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 | #include <iostream> #include <algorithm> #include <vector> #include "message.h" #include "palindromy.h" #define debug 0 using namespace std; int id; char Get(int a) { // TODO if (debug) cout << "ask for " << id << " about " << a << endl; return GetLetter(a); } long long add(int a, int prom, bool niep); //From Algorytmika Praktyczna: long long PalRad(int start, int fin, bool niep) { if (debug) cout << "palindromy for " << id << " params: " << start << ", " << fin << ", " << niep << endl; int n = fin - start, i = 1, j = 0, k; vector<int> r(n, 0); //200 MB long long ans = 0; while (i < n) { // while (i + j + niep <= n && i - j > 0 && Get(start + i - j - 1) == Get(start + i + j + niep)) while (i + j + niep < n && i - j > 0 && Get(start + i - j - 1) == Get(start + i + j + niep)) j++; r[i] = j; k = 1; while (r[i - k] != j - k && k <= j) { r[i + k] = min(r[i - k], j - k); ++k; } j = max(0, j - k); i += k; } for (unsigned a = 0; a < r.size(); ++a) { //cout << "xxx " << a + start << " niep = " << niep << ": " << r[a] << ", " << a << ", " << fin - a -niep << endl; if (r[a] == a || r[a] == fin - start - a - niep) { r[a] = add(a, r[a], niep); } ans += r[a]; //cout << "value for " << niep << ", " << a + start << " r = " << r[a] << " by " << id << endl; } return ans; } long long ans; long long p1 = 99194853094755497ll, p2 = 2305843009213693951ll; int n, maxId, k; int start, fin; int step = 1000; inline long long calc_hash(long long h, long long a) { return (h * p1 + a) % p2; } // GetLetter // GetLength vector<long long> prev_all(100), next_all(100); // malo long long my_all_to_r, my_all_to_l; // malo vector<long long> prev_step[100], next_step[100]; // 4 MB vector<long long> my_to_r, my_to_l; // 0.8 MB bool takie_same(int s1, int e1, int s2, int e2) { //return wether [s1, e1) = [s2, e2) //TODO for (int i = s1; i < e1; ++i) { if (Get(i) != Get(i - s1 + s2)) return false; } return true; } bool ok(int a, int s, int prom, bool niep) { // w a jest palindrom niep o promieniu prom. czy jest tez o promieniu s? bool ans = takie_same(a - s, a - prom, a + niep + prom, a + niep + s); //cout << "ok " << a << " with niep = " << niep << " ans = " << ans << endl; return ans; } long long add(int a, int prom, bool niep) { int pos = a + start; //cout << "pos = " << pos << " niep = " << niep << endl; while (pos - prom - 1 >= 0 && pos + prom + niep < n && Get(pos-prom-1) == Get(pos + prom + niep)) ++prom; return prom; /* int end = min(pos + 1, 1 + n - pos - niep); cout << "add by " << id << " with " << pos << ", " << prom << ", " << niep << ". end = " << end << endl; while (prom + 1 < end) { int s = (prom + end)/2; if (ok(pos, s, prom, niep)) prom = s; else end = s; } return prom; */ } void calc_hashes() { //to right int ile = 0; long long h = 0; for (int i = start; i < fin; ++i) { h = calc_hash(h, Get(i)); ++ile; if (ile % step == 0) my_to_r.push_back(h); } my_all_to_r = h; //to left h = 0; ile = 0; for (int i = fin - 1; i >= start; --i) { h = calc_hash(h, Get(i)); ++ile; if (ile % step == 0) my_to_l.push_back(h); } my_all_to_l = h; for (int i = 0; i < id; ++i) { PutLL(i, my_all_to_r); PutInt(i, my_to_r.size()); for (unsigned j = 0; j < my_to_r.size(); ++j) { PutLL(i, my_to_r[j]); } Send(i); } for (int i = id+1; i < maxId; ++i) { PutLL(i, my_all_to_l); PutInt(i, my_to_l.size()); for (unsigned j = 0; j < my_to_l.size(); ++j) { PutLL(i, my_to_l[j]); } Send(i); } for (int i = 1; i < maxId; ++i) { int from = Receive(-1); if (debug) cout << "received for " << id << " from " << from << endl; if (from > id) { // read to next next_all[from] = GetLL(from); int s = GetInt(from); for (int j = 0; j < s; ++j) next_step[from].push_back(GetLL(from)); } else { prev_all[from] = GetLL(from); int s = GetInt(from); for (int j = 0; j < s; ++j) prev_step[from].push_back(GetLL(from)); } } } int main() { n = GetLength(); id = MyNodeId(); maxId = NumberOfNodes(); if (n < maxId) maxId = n; k = n / maxId; start = k * id; fin = start + k; if (id == maxId - 1) fin = n; if (id >= maxId) return 0; calc_hashes(); ans += PalRad(start, fin, 1); ans += PalRad(start, fin, 0); ans += fin - start; if (id > 0) { PutLL(0, ans); Send(0); } else { for (int i = 1; i < maxId; ++i) { int from = Receive(-1); ans += GetLL(from); } cout << ans << endl; } return 0; } |