#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma comment (linker, "/STACK:256000000") #pragma GCC optimize("Ofast") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") using namespace std; const int maxN = 60000; int m, n; int c[maxN]; int s[maxN]; int d[maxN]; int p[maxN]; vector < int > a[maxN][4], b[maxN][4]; int w[maxN][4]; int r[maxN]; int res[maxN]; int t[4][maxN]; void update(int t[], int k, int delta) { for (int i = k; i < maxN; i |= (i + 1)) { t[i] += delta; } } int get(int t[], int k) { int res = 0; for (int i = k; i >= 0; i = (i & (i + 1)) - 1) { res += t[i]; } return res; } int get(int t[], int l, int r) { return get(t, r) - get(t, l - 1); } int rt[2][4 * maxN], ra[2][4 * maxN]; void update(int rt[], int ra[], int i, int l, int r, int cl, int cr, int value) { if (l == cl && r == cr) { ra[i] += value; rt[i] += value; return; } if (cl > (l + r) / 2) { update(rt, ra, 2 * i + 1, (l + r) / 2 + 1, r, cl, cr, value); } else if (cr <= (l + r) / 2) { update(rt, ra, 2 * i, l, (l + r) / 2, cl, cr, value); } else { update(rt, ra, 2 * i, l, (l + r) / 2, cl, (l + r) / 2, value); update(rt, ra, 2 * i + 1, (l + r) / 2 + 1, r, (l + r) / 2 + 1, cr, value); } rt[i] = max(rt[2 * i], rt[2 * i + 1]) + ra[i]; } int get(int rt[], int ra[], int i, int l, int r, int cl, int cr) { if (l == cl && r == cr) { return rt[i]; } if (cl > (l + r) / 2) { return get(rt, ra, 2 * i + 1, (l + r) / 2 + 1, r, cl, cr) + ra[i]; } if (cr <= (l + r) / 2) { return get(rt, ra, 2 * i, l, (l + r) / 2, cl, cr) + ra[i]; } return max( get(rt, ra, 2 * i, l, (l + r) / 2, cl, (l + r) / 2), get(rt, ra, 2 * i + 1, (l + r) / 2 + 1, r, (l + r) / 2 + 1, cr)) + ra[i]; } void solve() { scanf("%d%d", &m, &n); for (int i = 0; i <= m; ++i) { for (int j = 0; j < 4; ++j) { a[i][j].clear(); b[i][j].clear(); w[i][j] = 0; } } for (int i = 0; i < n; ++i) { char s[5]; scanf("%s", &s); if (s[0] == 'E') { c[i] = 0; } else if (s[0] == 'D') { c[i] = 1; } else if (s[0] == 'C') { c[i] = 2; } else { c[i] = 3; } } for (int i = 0; i < n; ++i) { scanf("%d", &s[i]); a[s[i]][c[i]].push_back(i); } for (int i = 0; i < n; ++i) { scanf("%d", &d[i]); if (s[i] <= d[i]) { b[d[i]][c[i]].push_back(i); } } for (int i = 0; i <= m; ++i) { r[i] = 0; } for (int i = 1; i <= n; ++i) { res[i] = m + 1; } memset(t, 0, sizeof(t)); memset(rt, 0, sizeof(rt)); memset(ra, 0, sizeof(ra)); for (int i = 1; i <= m; ++i) { for (int j = 0; j < 4; ++j) { for (int k = 0; k < b[i][j].size(); ++k) { int pos = s[b[i][j][k]]; int index = (j == 0 || j == 2) ? 0 : 1; update(rt[index], ra[index], 1, 0, m, 0, pos, 1); } } r[i] = max(get(rt[0], ra[0], 1, 0, m, 0, i - 1), get(rt[1], ra[1], 1, 0, m, 0, i - 1)); update(rt[0], ra[0], 1, 0, m, i, m, r[i] - r[i - 1]); update(rt[1], ra[1], 1, 0, m, i, m, r[i] - r[i - 1]); res[r[i]] = min(res[r[i]], i); } /*int prev = 0; for (int i = 1; i <= m; ++i) { vector < int > candidates; for (int j = 0; j < 4; ++j) { for (int k = 0; k < b[i][j].size(); ++k) { update(t[j], s[b[i][j][k]], 1); ++w[s[b[i][j][k]]][j]; candidates.push_back(s[b[i][j][k]]); } } int mm = max(b[i][0].size() + b[i][2].size(), b[i][1].size() + b[i][3].size()); int gscore = r[i - 1] + mm; sort(candidates.begin(), candidates.end()); candidates.resize(unique(candidates.begin(), candidates.end()) - candidates.begin()); int x = 0, y = 0; int D = 3000; int best = -1; int nx = get(t[0], prev, i - 1) + get(t[2], prev, i - 1); int ny = get(t[1], prev, i - 1) + get(t[3], prev, i - 1); x = nx, y = ny; for (int j = prev; j <= prev + D && j < i && r[i] < gscore; ++j) { int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } x -= w[j][0] + w[j][2]; y -= w[j][1] + w[j][3]; } x = nx, y = ny; for (int j = prev - 1; j >= prev - D && j > 0 && r[i] < gscore; --j) { x += w[j][0] + w[j][2]; y += w[j][1] + w[j][3]; int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } } for (int et = 0; et < candidates.size() && r[i] < gscore; ++et) { int pos = candidates[et]; int nt = (et + 1 == candidates.size() ? i : candidates[et + 1]); int pt = (et == 0 ? 0 : candidates[et - 1]); int nx = get(t[0], pos, i - 1) + get(t[2], pos, i - 1); int ny = get(t[1], pos, i - 1) + get(t[3], pos, i - 1); x = nx, y = ny; for (int j = pos; j <= pos + 50 && j < nt && r[i] < gscore; ++j) { int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } x -= w[j][0] + w[j][2]; y -= w[j][1] + w[j][3]; } x = nx, y = ny; for (int j = pos - 1; j >= pos - 50 && j > pt && r[i] < gscore; --j) { x += w[j][0] + w[j][2]; y += w[j][1] + w[j][3]; int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } } } x = 0, y = 0; for (int j = i - 1; j >= i - D && j >= prev + D && r[i] < gscore; --j) { x += w[j][0] + w[j][2]; y += w[j][1] + w[j][3]; int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } r[i] = max(max(x, y) + r[j], r[i]); } x = get(t[0], 0, i - 1) + get(t[2], 0, i - 1); y = get(t[1], 0, i - 1) + get(t[3], 0, i - 1); for (int j = 1; j <= D && j < prev - D && r[i] < gscore; ++j) { int u = max(x, y) + r[j]; if (u > r[i]) { r[i] = u; best = j; } x -= w[j][0] + w[j][2]; y -= w[j][1] + w[j][3]; } prev = best; res[r[i]] = min(res[r[i]], i); if (r[i] == n) { break; } //cerr << i << " " << r[i] << endl; }*/ for (int i = n - 1; i >= 1; --i) { res[i] = min(res[i], res[i + 1]); } for (int i = 1; i <= n; ++i) { if (res[i] > m) { res[i] = -1; } printf("%d ", res[i]); } printf("\n"); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int t; scanf("%d", &t); for (int i = 0; i < t; ++i) { solve(); } return 0; }