// Kacper Orszulak #include <cstdio> #include <vector> #define fft(n) for (int i = 0; i < n; ++i) // Fast For Transform using namespace std; using pii = pair<int, int>; constexpr pii INVALID_POINT(-1, -1); inline bool amogus(int x, int a, int b) { return a <= x && x <= b; } int n, queries_cnt; vector<int> arr[2]; vector<pii> pos_of; int result[10+1]; struct fau_t { vector<int> rep; vector<int> subset_size; void reset(int size) { rep.resize(size); for (int i = 0; i < size; ++i) rep[i] = i; subset_size.assign(size, 1); } int find(int x) { if (rep[x] == x) return x; else return rep[x] = find(rep[x]); } void union_(int a, int b) { a = find(a); b = find(b); if (a == b) return; if (subset_size[a] > subset_size[b]) swap(a, b); subset_size[b] += subset_size[a]; subset_size[a] = 0; rep[a] = b; } }; pii get_neighbor(pii v, const int id) { switch (id) { case 0: --v.first; break; case 1: ++v.first; break; case 2: --v.second; break; case 3: ++v.second; break; default: return INVALID_POINT; } v.second = (v.second+n)%n; if (v.first < 0 || v.first > 1) return INVALID_POINT; return v; } void subtask3() { fau_t fau; for (int l = 0; l < 2*n; ++l) { fau.reset(2*n); int subsets_cnt = 0; for (int r = l; r < 2*n; ++r) { const int v_color = r; const pii v = pos_of[v_color]; ++subsets_cnt; for (int id = 0; id < 4; ++id) { const pii w = get_neighbor(v, id); if (w == INVALID_POINT) continue; const int w_color = arr[w.first][w.second]; if (!amogus(w_color, l, r)) continue; const int v_rep = fau.find(v_color); const int w_rep = fau.find(w_color); if (v_rep == w_rep) continue; fau.union_(v_rep, w_rep); --subsets_cnt; } if (subsets_cnt <= 10) ++result[subsets_cnt]; } } } int main(void) { scanf("%d %d", &n, &queries_cnt); arr[0].resize(n); arr[1].resize(n); pos_of.resize(2*n); for (int i = 0; i < n; ++i) { int &e = arr[0][i]; scanf("%d", &e); --e; pos_of[e] = {0, i}; } for (int i = 0; i < n; ++i) { int &e = arr[1][i]; scanf("%d", &e); --e; pos_of[e] = {1, i}; } subtask3(); for (int v = 1; v <= queries_cnt; ++v) printf("%d ", result[v]); printf("\n"); 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 | // Kacper Orszulak #include <cstdio> #include <vector> #define fft(n) for (int i = 0; i < n; ++i) // Fast For Transform using namespace std; using pii = pair<int, int>; constexpr pii INVALID_POINT(-1, -1); inline bool amogus(int x, int a, int b) { return a <= x && x <= b; } int n, queries_cnt; vector<int> arr[2]; vector<pii> pos_of; int result[10+1]; struct fau_t { vector<int> rep; vector<int> subset_size; void reset(int size) { rep.resize(size); for (int i = 0; i < size; ++i) rep[i] = i; subset_size.assign(size, 1); } int find(int x) { if (rep[x] == x) return x; else return rep[x] = find(rep[x]); } void union_(int a, int b) { a = find(a); b = find(b); if (a == b) return; if (subset_size[a] > subset_size[b]) swap(a, b); subset_size[b] += subset_size[a]; subset_size[a] = 0; rep[a] = b; } }; pii get_neighbor(pii v, const int id) { switch (id) { case 0: --v.first; break; case 1: ++v.first; break; case 2: --v.second; break; case 3: ++v.second; break; default: return INVALID_POINT; } v.second = (v.second+n)%n; if (v.first < 0 || v.first > 1) return INVALID_POINT; return v; } void subtask3() { fau_t fau; for (int l = 0; l < 2*n; ++l) { fau.reset(2*n); int subsets_cnt = 0; for (int r = l; r < 2*n; ++r) { const int v_color = r; const pii v = pos_of[v_color]; ++subsets_cnt; for (int id = 0; id < 4; ++id) { const pii w = get_neighbor(v, id); if (w == INVALID_POINT) continue; const int w_color = arr[w.first][w.second]; if (!amogus(w_color, l, r)) continue; const int v_rep = fau.find(v_color); const int w_rep = fau.find(w_color); if (v_rep == w_rep) continue; fau.union_(v_rep, w_rep); --subsets_cnt; } if (subsets_cnt <= 10) ++result[subsets_cnt]; } } } int main(void) { scanf("%d %d", &n, &queries_cnt); arr[0].resize(n); arr[1].resize(n); pos_of.resize(2*n); for (int i = 0; i < n; ++i) { int &e = arr[0][i]; scanf("%d", &e); --e; pos_of[e] = {0, i}; } for (int i = 0; i < n; ++i) { int &e = arr[1][i]; scanf("%d", &e); --e; pos_of[e] = {1, i}; } subtask3(); for (int v = 1; v <= queries_cnt; ++v) printf("%d ", result[v]); printf("\n"); return 0; } |