// 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; } |
English