#include #define llong long long #define f first #define s second #define mp make_pair using namespace std; ifstream fin ("Cin.txt"); struct SegTree { struct Segment { int start, finish, mid; int val; int lazy; }; vector stree; SegTree(int N) { int siz = 1; while (siz < 2 * N) { siz *= 2; } stree.resize(siz); } void build(int pos, int start, int finish) { stree[pos].start = start; stree[pos].finish = finish; /// check if pos is leaf, then leave if (start == finish) { stree[pos].val = 0; return; } stree[pos].mid = (start + finish) / 2; build(2 * pos, start, stree[pos].mid); build(2 * pos + 1, stree[pos].mid + 1, finish); stree[pos].val = max(stree[2 * pos].val, stree[2 * pos + 1].val); return; } void propagate(int pos) { Segment &seg = stree[pos]; seg.val += seg.lazy; /// check if pos isn't leaf if (seg.start != seg.finish) { /// propagate .lazy stree[2 * pos].lazy += seg.lazy; stree[2 * pos + 1].lazy += seg.lazy; } seg.lazy = 0; } void modify_add(int pos, int l, int r, int val) { Segment &seg = stree[pos]; if (seg.lazy != 0) { propagate(pos); } /// check if segment is inside the query if (l <= seg.start && seg.finish <= r) { seg.lazy += val; propagate(pos); return; } /// check if stree[pos] is leaf node if (seg.start == seg.finish) { return; } /// check if range is outside the segment if (r < seg.start || l > seg.finish) { return; } /// recurse on children modify_add(2 * pos, l, r, val); modify_add(2 * pos + 1, l, r, val); /// since children don't have any pending updates (their .lazy is 0), we can safely add their val to current node seg.val = max(stree[2 * pos].val, stree[2 * pos + 1].val); } int query(int pos, int l, int r) { Segment &seg = stree[pos]; /// update if needed if (seg.lazy != 0) { propagate(pos); } /// check if range is outside the segment if (r < seg.start || l > seg.finish) { return 0; } /// check if segment is inside the range if (l <= seg.start && seg.finish <= r) { return seg.val; } /// recurse on children int p1 = query(2 * pos, l, r); int p2 = query(2 * pos + 1, l, r); return max(p1, p2); } }; struct animal { int type; int from; int to; }; bool comp(const animal& a, const animal& b) { if (a.to != b.to) { return a.to < b.to; } return a.from < b.from; } int main() { int T; cin >> T; for (int t = 0; t < T; t++) { int N, M; cin >> M >> N; vector animals(N); for (int i = 0; i < N; i++) { char t; cin >> t; if (t == 'E' || t == 'C') { animals[i].type = 0; } else { animals[i].type = 1; } } for (int i = 0; i < N; i++) { int u; cin >> u; animals[i].from = u - 1; } for (int i = 0; i < N; i++) { int u; cin >> u; animals[i].to = u - 1; } sort(animals.begin(), animals.end(), comp); vector > incoming(M, vector (0)); vector complement(2, SegTree(M)); vector > dp(2, vector(M)); vector tot_dp(M); for (int i = 0; i < N; i++) { if (animals[i].from < animals[i].to) incoming[animals[i].to].push_back(i); } for (int t = 0; t < 2; t++) { complement[t].build(1, 0, M - 1); } for (int x = 1; x < M; x++) { dp[0][x] = dp[0][x - 1]; dp[1][x] = dp[1][x - 1]; for (auto id : incoming[x]) { if (animals[id].from < animals[id].to) complement[animals[id].type ^ 1].modify_add(1, 0, animals[id].from, 1); } for (int t = 0; t < 2; t++) { dp[t][x] = max(complement[t ^ 1].query(1, 0, x - 1), dp[t][x]); } complement[0].modify_add(1, x, x, dp[0][x]); complement[1].modify_add(1, x, x, dp[1][x]); tot_dp[x] = max(dp[0][x], dp[1][x]); } int pos = 0; for (int val = 1; val <= N; val++) { while (tot_dp[pos] < val && pos < M) { pos++; } if (pos == M) { cout << "-1 "; } else { cout << pos + 1 << " "; } } cout << "\n"; } }