#pragma GCC optimize("Ofast") #pragma GCC target("avx") #include #include #include #include #include using namespace std; constexpr int kMaxN = 50000, kNumAnimals = 4, kBuckets = 512; constexpr char kAnimals[4] = {'E', 'D', 'C', 'M'}; constexpr int masks[6] = {1, 2, 4, 5, 8, 10}; int ans[kMaxN + 1]; int add[kMaxN][6]; int dp[kMaxN]; int dp_buckets[(kMaxN - 1) / kBuckets + 1][6]; int add_buckets[(kMaxN - 1) / kBuckets + 1][6]; void SolveTest() { int m, n; cin >> m >> n; vector> intervals(n); for (int i = 0; i < n; i += 1) { char type; cin >> type; int j = 0; while (kAnimals[j] != type) { j += 1; } get<0>(intervals[i]) = j; } for (int i = 0; i < n; i += 1) { int x; cin >> x; get<1>(intervals[i]) = x - 1; } for (int i = 0; i < n; i += 1) { int x; cin >> x; get<2>(intervals[i]) = x - 1; } for (int i = n - 1; i >= 0; i -= 1) { if (get<1>(intervals[i]) > get<2>(intervals[i])) { swap(intervals[i], intervals.back()); intervals.pop_back(); } } sort(intervals.begin(), intervals.end(), [](const tuple& a, const tuple& b) { return make_pair(get<2>(a), -get<1>(a)) < make_pair(get<2>(b), -get<1>(b)); }); memset(add, 0, sizeof add); memset(ans, 0x3f, sizeof ans); memset(dp, 0, sizeof dp); memset(dp_buckets, 0, sizeof dp_buckets); memset(add_buckets, 0, sizeof add_buckets); for (int i = 0, j = 0; i < m; i += 1) { int former_j = j; while (j < (int)intervals.size() and get<2>(intervals[j]) <= i) { for (int k = 0; k < 6; k += 1) { if ((masks[k] >> get<0>(intervals[j])) & 1) { //add[get<1>(intervals[j])][k] += 1; int iter = 0; while (iter + kBuckets - 1 <= get<1>(intervals[j])) { add_buckets[iter / kBuckets][k] += 1; iter += kBuckets; } while (iter <= get<1>(intervals[j])) { add[iter][k] += 1; if (dp_buckets[iter / kBuckets][k] < dp[iter] + add[iter][k]) { dp_buckets[iter / kBuckets][k] = dp[iter] + add[iter][k]; } iter += 1; } } } j += 1; } int iter = 0; while (iter + kBuckets - 1 <= i - 1) { for (int k = 0; k < 6; k += 1) { if (dp_buckets[iter / kBuckets][k] + add_buckets[iter / kBuckets][k] > dp[i]) { dp[i] = dp_buckets[iter / kBuckets][k] + add_buckets[iter / kBuckets][k]; } } iter += kBuckets; } while (iter <= i - 1) { for (int k = 0; k < 6; k += 1) { if (dp[iter] + add[iter][k] + add_buckets[iter / kBuckets][k] > dp[i]) { dp[i] = dp[iter] + add[iter][k] + add_buckets[iter / kBuckets][k]; } } iter += 1; } for (int k = 0; k < 6; k += 1) { if (dp_buckets[iter / kBuckets][k] < dp[i]) { dp_buckets[i / kBuckets][k] = dp[i]; } } if (ans[dp[i]] > i) { ans[dp[i]] = i; } } for (int i = n - 1; i > 0; i -= 1) { ans[i] = min(ans[i], ans[i + 1]); } for (int i = 1; i <= n; i += 1) { if (ans[i] == 0x3f3f3f3f) { ans[i] = -2; } cout << ans[i] + 1 << " \n"[i == n]; } } int main() { int num_tests; cin >> num_tests; while (num_tests--) { SolveTest(); } return 0; }