#region Usings using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using static System.Array; using static System.Math; // ReSharper disable InconsistentNaming #pragma warning disable CS0675 #endregion partial class Solution { int m, n; int[] answers; Animal[] animals; int[] MinimumZooNumbers() { answers = new int[n]; var fts = new[] { new FenwickTree(m), new FenwickTree(m) }; int[][] transportmax = { new int[m], new int[m] }; int[][] transportindex = { new int[m], new int[m] }; int zoo = 1; var indices = new HashSet(); var indices2 = new List(); for (int j = 0; j <= animals.Length; j++) { int z = j < animals.Length ? animals[j].End : m - 1; while (true) { for (int ti = 0; ti < 2; ti++) { Update(ref transportmax[ti][zoo], ref transportindex[ti][zoo], transportmax[ti][zoo - 1], transportindex[ti][zoo - 1]); } if (zoo >= z) break; zoo++; } if (j >= animals.Length) break; int start = j; for (; j < animals.Length; j++) { fts[animals[j].Type].Add(animals[j].Start, 1); if (j + 1 >= animals.Length || z != animals[j + 1].End) break; } if (n > 3000) { for (int k = start; k <= j; k++) { var an = animals[k]; var ti = an.Type; var max = transportmax[ti][z]; var ind = transportindex[ti][z]; indices.Clear(); indices.Add(an.Start); indices.Add(z - 1); indices.Add(transportindex[ti][z - 1]); indices.Add(transportindex[ti][an.Start]); indices.Add(transportindex[ti][an.Start - 1]); indices.Add(transportindex[1 - ti][z - 1]); indices.Add(transportindex[1 - ti][an.Start]); indices.Add(transportindex[1 - ti][an.Start - 1]); indices2.Clear(); indices2.AddRange(indices); foreach (var v in indices2) { var v2 = fts[ti].Previous(v + 1); if (v2 > v && v2 < z) indices.Add(v2); v2 = fts[ti].Next(v - 1); if (v2 > v && v2 < z) indices.Add(v2); } foreach (var v in indices) { var add = (int)fts[ti].SumInclusive(v, z); var tmp = transportmax[1 - ti][v] + add; Update(ref max, ref ind, tmp, v); tmp = transportmax[ti][v] + add; Update(ref max, ref ind, tmp, v); } Update(ref transportmax[ti][z], ref transportindex[ti][z], max, ind); } for (int ti = 0; ti < 2; ti++) { var scan = Max(z >> 5, 1); for (int kk = 0; kk < z; kk += scan) { var magic = transportindex[ti][kk]; var v2 = fts[ti].Next(magic - 1); if (v2 < magic || v2 > z) v2 = magic; var add = (int)fts[ti].SumInclusive(v2, z); var tmp = transportmax[1 - ti][v2] + add; Update(ref transportmax[ti][z], ref transportindex[ti][z], tmp, magic); tmp = transportmax[ti][v2] + add; Update(ref transportmax[ti][z], ref transportindex[ti][z], tmp, magic); } } } else { for (int ti = 0; ti < 2; ti++) { var max = transportmax[ti][z]; for (int k = 0; k < z; k++) { var tmp = transportmax[1 - ti][k] + fts[ti].SumInclusive(k, z); if (tmp > max) max = (int)tmp; } transportmax[ti][z] = max; } } } int[] maxtransport01 = new int[m]; for (int i = 0; i < maxtransport01.Length; i++) maxtransport01[i] = Max(transportmax[0][i], transportmax[1][i]); for (int i = 0; i < answers.Length; i++) { var tmp = Bound(maxtransport01, i + 1); answers[i] = tmp < m ? tmp : -1; } return answers; } int[] MinimumZooNumbers2() { answers = new int[n]; var sts = new[] {new LazySegmentTree(m), new LazySegmentTree(m)}; for (int i = 0; i < answers.Length; i++) answers[i] = int.MaxValue; for (int j = 0; j < animals.Length; j++) { int zoo = animals[j].End; for (; j < animals.Length; j++) { sts[animals[j].Type].AddInclusive(0, animals[j].Start, 1); if (j + 1 >= animals.Length || zoo != animals[j + 1].End) break; } int curMax = Max(sts[0].GetMaxInclusive(0, zoo), sts[1].GetMaxInclusive(0, zoo)); sts[0].CoverInclusive(zoo, zoo, curMax); sts[1].CoverInclusive(zoo, zoo, curMax); answers[curMax-1] = Math.Min(answers[curMax-1], zoo); } int min = int.MaxValue; for (int i=n-1; i>=0; i--) { min = Math.Min(answers[i], min); answers[i] = min==int.MaxValue ? -1 : min; } return answers; } public static int[] CompressX(int[] a) { int n = a.Length; var ret = (int[])a.Clone(); int[] ind = new int[n]; for (int i = 0; i < n; i++) ind[i] = i; Array.Sort(ret, ind); int p = 0; for (int i = 0; i < n; i++) { if (i == 0 || ret[i] != ret[i - 1]) ret[p++] = ret[i]; a[ind[i]] = p - 1; } Array.Resize(ref ret, p); return ret; } void Update(ref int max, ref int ind, int max2, int ind2) { if (max > max2 || max == max2 && ind <= ind2) return; max = max2; ind = ind2; } void Solve() { int cases = Ni(); for (int a0 = 0; a0 < cases; a0++) { m = Ni() + 1; n = Ni(); var t = N(n, () => { var c = Ns()[0]; return c == 'D' || c == 'M' ? 0 : 1; }); var s = Ni(n); var d = Ni(n); var list = new List(); for (int i = 0; i < n; i++) { if (s[i] <= d[i]) list.Add(new Animal { Type = t[i], Start = s[i], End = d[i] }); } list.Sort((a, b) => { int cmp = a.End.CompareTo(b.End); if (cmp != 0) return cmp; return -a.Start.CompareTo(b.Start); }); animals = list.ToArray(); int[] result = MinimumZooNumbers2(); WriteLine(string.Join(" ", result)); } } class Animal { public int Start; public int End; public int Type; } public class FenwickTree { #region Variables public readonly long[] A; #endregion #region Constructor /*public Fenwick(int[] a) : this(a.Length) { for (int i = 0; i < a.Length; i++) Add(i, a[i]); }*/ public FenwickTree(long[] a) : this(a.Length) { int n = a.Length; System.Array.Copy(a, 0, A, 1, n); for (int k = 2, h = 1; k <= n; k *= 2, h *= 2) { for (int i = k; i <= n; i += k) A[i] += A[i - h]; } //for (int i = 0; i < a.Length; i++) // Add(i, a[i]); } public FenwickTree(long size) { A = new long[size + 1]; } #endregion #region Properties public long this[int index] => AltRangeUpdatePointQueryMode ? SumInclusive(index) : SumInclusive(index, index); public int Length => A.Length - 1; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public long[] Table { get { int n = A.Length - 1; long[] ret = new long[n]; for (int i = 0; i < n; i++) ret[i] = SumInclusive(i); if (!AltRangeUpdatePointQueryMode) for (int i = n - 1; i >= 1; i--) ret[i] -= ret[i - 1]; return ret; } } #endregion #region Methods // Increments value /// /// Adds val to the value at i /// /// The i. /// The value. public void Add(int i, long val) { if (val == 0) return; for (i++; i < A.Length; i += (i & -i)) A[i] += val; } // Sum from [0 ... i] public long SumInclusive(int i) { long sum = 0; for (i++; i > 0; i -= (i & -i)) sum += A[i]; return sum; } public long SumInclusive(int i, int j) { return SumInclusive(j) - SumInclusive(i - 1); } // get largest value with cumulative sum less than x; // for smallest, pass x-1 and add 1 to result public int GetIndexGreater(long x) { int i = 0, n = A.Length - 1; for (int bit = HighestOneBit(n); bit != 0; bit >>= 1) { int t = i | bit; // if (t <= n && Array[t] < x) for greater or equal if (t <= n && A[t] <= x) { i = t; x -= A[t]; } } return i; } public int Next(int x) { var iafter = GetIndexGreater(SumInclusive(x)); if (iafter >= Length) return -1; return iafter; } public int Previous(int x) { if (x <= 0) return -1; var count = SumInclusive(x - 1); if (count == 0) return -1; return GetIndexGreater(count - 1); } #endregion #region Alternative Range Update Point Query Mode ( cf Standard Point Update Range Query ) #pragma warning disable 649 public bool AltRangeUpdatePointQueryMode; #pragma warning restore 649 /// /// Inclusive update of the range [left, right] by value /// The default operation of the fenwick tree is point update - range query. /// We use this if we want alternative range update - point query. /// SumInclusive becomes te point query function. /// /// public void AltAddInclusive(int left, int right, long delta) { Add(left, delta); Add(right + 1, -delta); } public long AltQuery(int index) { return SumInclusive(index); } #endregion } public class LazySegmentTree { public int Max = int.MinValue; public int Sum; public int LazyAdd; public int Start; public int End; public LazySegmentTree Left; public LazySegmentTree Right; public bool Covering; public int Length => End - Start + 1; public LazySegmentTree(int n) : this(null, 0, n - 1) { } public LazySegmentTree(int[] array) : this(array, 0, array.Length - 1) { } LazySegmentTree(int[] array, int start, int end) { Start = start; End = end; if (end > start) { int mid = (start + end) / 2; Left = new LazySegmentTree(array, start, mid); Right = new LazySegmentTree(array, mid + 1, end); UpdateNode(); } else { var v = array != null ? array[start] : 0; Max = v; Sum = v; } } public int GetSumInclusive(int start, int end) { if (Start >= start && End <= end) return Sum; if (start > End || end < Start) return 0; LazyPropagate(); return Left.GetSumInclusive(start, end) + Right.GetSumInclusive(start, end); } public int GetMaxInclusive(int start, int end) { if (Start >= start && End <= end) return Max; if (start > End || end < Start) return int.MinValue; LazyPropagate(); return Max(Left.GetMaxInclusive(start, end), Right.GetMaxInclusive(start, end)); } public void AddInclusive(int start, int end, int value) { if (start > End || end < Start) return; if (Start >= start && End <= end) { Add(value); return; } LazyPropagate(); Left.AddInclusive(start, end, value); Right.AddInclusive(start, end, value); UpdateNode(); } void Add(int value) { Sum += value * Length; Max += value; LazyAdd += value; } void LazyPropagate() { if (Start == End) return; if (Covering) { Left.Cover(Max); Right.Cover(Max); LazyAdd = 0; Covering = false; return; } if (LazyAdd != 0) { var value = LazyAdd; LazyAdd = 0; Left.Add(value); Right.Add(value); } } void UpdateNode() { var left = Left; var right = Right; Sum = left.Sum + right.Sum; Max = Max(left.Max, right.Max); } public void CoverInclusive(int start, int end, int value) { if (start > End || end < Start) return; if (Start >= start && End <= end) { Cover(value); return; } LazyPropagate(); Left.CoverInclusive(start, end, value); Right.CoverInclusive(start, end, value); UpdateNode(); } void Cover(int value) { Max = value; LazyAdd = 0; Sum = value * Length; Covering = true; } } #region Mod Math public const int MOD = 1000000007; const int FactCache = 1000; static int[] _inverse; public static long Inverse(long n) { long result; if (_inverse == null) _inverse = new int[3000]; if (n < _inverse.Length && (result = _inverse[n]) != 0) return result - 1; result = ModPow(n, MOD - 2); if (n < _inverse.Length) _inverse[n] = (int)(result + 1); return result; } public static long Mult(long left, long right) => (left * right) % MOD; public static long Div(long left, long divisor) => left * Inverse(divisor) % MOD; public static long Add(long x, long y) => (x += y) >= MOD ? x - MOD : x; public static long Subtract(long x, long y) => (x -= y) < 0 ? x + MOD : x; public static long Fix(long n) => (n %= MOD) >= 0 ? n : n + MOD; public static long ModPow(long n, long p, long mod = MOD) { long b = n; long result = 1; while (p != 0) { if ((p & 1) != 0) result = (result * b) % mod; p >>= 1; b = (b * b) % mod; } return result; } static List _fact, _ifact; public static long Fact(int n) { if (_fact == null) _fact = new List(FactCache) { 1 }; for (int i = _fact.Count; i <= n; i++) _fact.Add(Mult(_fact[i - 1], i)); return _fact[n]; } public static long InverseFact(int n) { if (_ifact == null) _ifact = new List(FactCache) { 1 }; for (int i = _ifact.Count; i <= n; i++) _ifact.Add(Div(_ifact[i - 1], i)); return _ifact[n]; } public static long Fact(int n, int m) { var fact = Fact(n); if (m < n) fact = fact * InverseFact(n - m) % MOD; return fact; } public static long Comb(int n, int k) { if (k <= 1) return k == 1 ? n : k == 0 ? 1 : 0; return Mult(Mult(Fact(n), InverseFact(k)), InverseFact(n - k)); } #endregion #region Common public static void Swap(ref T a, ref T b) { var tmp = a; a = b; b = tmp; } public static void Clear(T[] t, T value = default(T)) { for (int i = 0; i < t.Length; i++) t[i] = value; } public static V Get(Dictionary dict, K key) where V : new() { V result; if (dict.TryGetValue(key, out result) == false) result = dict[key] = new V(); return result; } public static int Bound(T[] array, T value, bool upper = false) where T : IComparable { int left = 0; int right = array.Length - 1; while (left <= right) { int mid = left + (right - left) / 2; int cmp = value.CompareTo(array[mid]); if (cmp > 0 || cmp == 0 && upper) left = mid + 1; else right = mid - 1; } return left; } public static long IntPow(long n, long p) { long b = n; long result = 1; while (p != 0) { if ((p & 1) != 0) result = (result * b); p >>= 1; b = (b * b); } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Log2(long value) { if (value <= 0) return value == 0 ? -1 : 63; var log = 0; if (value >= 0x100000000L) { log += 32; value >>= 32; } if (value >= 0x10000) { log += 16; value >>= 16; } if (value >= 0x100) { log += 8; value >>= 8; } if (value >= 0x10) { log += 4; value >>= 4; } if (value >= 0x4) { log += 2; value >>= 2; } if (value >= 0x2) { log += 1; } return log; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int BitCount(long x) { int count; var y = unchecked((ulong)x); for (count = 0; y != 0; count++) y &= y - 1; return count; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int HighestOneBit(int n) => n != 0 ? 1 << Log2(n) : 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long HighestOneBit(long n) => n != 0 ? 1L << Log2(n) : 0; #endregion #region Fast IO #region Input static System.IO.Stream inputStream; static int inputIndex, bytesRead; static byte[] inputBuffer; static System.Text.StringBuilder builder; const int MonoBufferSize = 4096; public static void InitInput(System.IO.Stream input = null, int stringCapacity = 16) { builder = new System.Text.StringBuilder(stringCapacity); inputStream = input ?? Console.OpenStandardInput(); inputIndex = bytesRead = 0; inputBuffer = new byte[MonoBufferSize]; } static void ReadMore() { if (bytesRead < 0) throw new FormatException(); inputIndex = 0; bytesRead = inputStream.Read(inputBuffer, 0, inputBuffer.Length); if (bytesRead > 0) return; bytesRead = -1; inputBuffer[0] = (byte)'\n'; } public static int Read() { if (inputIndex >= bytesRead) ReadMore(); return inputBuffer[inputIndex++]; } public static T[] N(int n, Func func) { var list = new T[n]; for (int i = 0; i < n; i++) list[i] = func(); return list; } public static int[] Ni(int n) => N(n, Ni); public static long[] Nl(int n) => N(n, Nl); public static string[] Ns(int n) => N(n, Ns); public static int Ni() => (int)Nl(); public static long Nl() { var c = SkipSpaces(); bool neg = c == '-'; if (neg) { c = Read(); } long number = c - '0'; while (true) { var d = Read() - '0'; if (unchecked((uint)d > 9)) break; number = number * 10 + d; if (number < 0) throw new FormatException(); } return neg ? -number : number; } public static char[] Nc(int n) { var list = new char[n]; for (int i = 0, c = SkipSpaces(); i < n; i++, c = Read()) list[i] = (char)c; return list; } public static string Ns() { var c = SkipSpaces(); builder.Clear(); while (true) { if (unchecked((uint)c - 33 >= (127 - 33))) break; builder.Append((char)c); c = Read(); } return builder.ToString(); } public static int SkipSpaces() { int c; do c = Read(); while (unchecked((uint)c - 33 >= (127 - 33))); return c; } public static string ReadLine() { builder.Clear(); while (true) { int c = Read(); if (c < 32) { if (c == 10 || c <= 0) break; continue; } builder.Append((char)c); } return builder.ToString(); } #endregion #region Output static System.IO.Stream outputStream; static byte[] outputBuffer; static int outputIndex; public static void InitOutput(System.IO.Stream output = null) { outputStream = output ?? Console.OpenStandardOutput(); outputIndex = 0; outputBuffer = new byte[65535]; } public static void WriteLine(object obj = null) { Write(obj); Write('\n'); } public static void WriteLine(long number) { Write(number); Write('\n'); } public static void Write(long signedNumber) { ulong number = unchecked((ulong)signedNumber); if (signedNumber < 0) { Write('-'); number = unchecked((ulong)(-signedNumber)); } Reserve(20 + 1); // 20 digits + 1 extra for sign int left = outputIndex; do { outputBuffer[outputIndex++] = (byte)('0' + number % 10); number /= 10; } while (number > 0); int right = outputIndex - 1; while (left < right) { byte tmp = outputBuffer[left]; outputBuffer[left++] = outputBuffer[right]; outputBuffer[right--] = tmp; } } public static void Write(object obj) { if (obj == null) return; var s = obj.ToString(); Reserve(s.Length); for (int i = 0; i < s.Length; i++) outputBuffer[outputIndex++] = (byte)s[i]; } public static void Write(char c) { Reserve(1); outputBuffer[outputIndex++] = (byte)c; } public static void Write(byte[] array, int count) { Reserve(count); Array.Copy(array, 0, outputBuffer, outputIndex, count); outputIndex += count; } static void Reserve(int n) { if (outputIndex + n <= outputBuffer.Length) return; Dump(); if (n > outputBuffer.Length) Array.Resize(ref outputBuffer, Math.Max(outputBuffer.Length * 2, n)); } static void Dump() { outputStream.Write(outputBuffer, 0, outputIndex); outputIndex = 0; } public static void Flush() { Dump(); outputStream.Flush(); } #endregion #endregion #region Main static void IncreaseStack(ThreadStart action, int stackSize = 16 * 1024 * 1024) { var thread = new Thread(action, stackSize); #if __MonoCS__ var f = BindingFlags.NonPublic | BindingFlags.Instance; var t = typeof(Thread).GetField("internal_thread", f).GetValue(thread); t.GetType().GetField("stack_size", f).SetValue(t, stackSize); #endif thread.Start(); thread.Join(); } public static void Main() { AppDomain.CurrentDomain.UnhandledException += (sender, arg) => { Flush(); var e = (Exception)arg.ExceptionObject; Console.Error.WriteLine(e); var line = new StackTrace(e, true).GetFrames() .Select(x => x.GetFileLineNumber()).FirstOrDefault(x => x != 0); var wait = line % 300 * 10 + 5; var process = Process.GetCurrentProcess(); while (process.TotalProcessorTime.TotalMilliseconds > wait && wait < 3000) wait += 1000; while (process.TotalProcessorTime.TotalMilliseconds < Math.Min(wait, 3000)) ; Environment.Exit(1); }; InitInput(Console.OpenStandardInput()); InitOutput(Console.OpenStandardOutput()); new Solution().Solve(); Flush(); Console.Error.WriteLine(Process.GetCurrentProcess().TotalProcessorTime); } #endregion }