結果
問題 | No.1698 Face to Face |
ユーザー | eSeF |
提出日時 | 2021-08-29 17:56:44 |
言語 | C# (.NET 8.0.203) |
結果 |
AC
|
実行時間 | 859 ms / 5,000 ms |
コード長 | 13,245 bytes |
コンパイル時間 | 8,604 ms |
コンパイル使用メモリ | 170,100 KB |
実行使用メモリ | 258,040 KB |
最終ジャッジ日時 | 2024-07-19 09:52:29 |
合計ジャッジ時間 | 30,257 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 55 ms
30,720 KB |
testcase_01 | AC | 55 ms
30,720 KB |
testcase_02 | AC | 57 ms
30,976 KB |
testcase_03 | AC | 513 ms
89,088 KB |
testcase_04 | AC | 541 ms
93,312 KB |
testcase_05 | AC | 704 ms
102,604 KB |
testcase_06 | AC | 680 ms
103,296 KB |
testcase_07 | AC | 690 ms
108,388 KB |
testcase_08 | AC | 668 ms
103,504 KB |
testcase_09 | AC | 677 ms
103,680 KB |
testcase_10 | AC | 531 ms
103,168 KB |
testcase_11 | AC | 730 ms
100,788 KB |
testcase_12 | AC | 812 ms
107,208 KB |
testcase_13 | AC | 58 ms
30,848 KB |
testcase_14 | AC | 57 ms
31,104 KB |
testcase_15 | AC | 855 ms
89,440 KB |
testcase_16 | AC | 844 ms
89,472 KB |
testcase_17 | AC | 838 ms
89,212 KB |
testcase_18 | AC | 734 ms
92,160 KB |
testcase_19 | AC | 726 ms
91,392 KB |
testcase_20 | AC | 686 ms
77,284 KB |
testcase_21 | AC | 397 ms
54,272 KB |
testcase_22 | AC | 309 ms
49,024 KB |
testcase_23 | AC | 132 ms
41,984 KB |
testcase_24 | AC | 492 ms
64,776 KB |
testcase_25 | AC | 859 ms
80,640 KB |
testcase_26 | AC | 108 ms
38,784 KB |
testcase_27 | AC | 226 ms
46,728 KB |
testcase_28 | AC | 243 ms
45,952 KB |
testcase_29 | AC | 193 ms
49,024 KB |
testcase_30 | AC | 482 ms
70,588 KB |
testcase_31 | AC | 356 ms
54,016 KB |
testcase_32 | AC | 602 ms
68,608 KB |
testcase_33 | AC | 592 ms
72,556 KB |
testcase_34 | AC | 819 ms
90,112 KB |
testcase_35 | AC | 56 ms
30,976 KB |
testcase_36 | AC | 57 ms
30,976 KB |
testcase_37 | AC | 55 ms
30,848 KB |
testcase_38 | AC | 56 ms
30,720 KB |
testcase_39 | AC | 55 ms
30,556 KB |
testcase_40 | AC | 56 ms
31,104 KB |
testcase_41 | AC | 56 ms
30,720 KB |
testcase_42 | AC | 56 ms
30,848 KB |
testcase_43 | AC | 55 ms
30,848 KB |
testcase_44 | AC | 58 ms
30,848 KB |
testcase_45 | AC | 603 ms
93,108 KB |
testcase_46 | AC | 580 ms
94,076 KB |
testcase_47 | AC | 739 ms
258,040 KB |
コンパイルメッセージ
復元対象のプロジェクトを決定しています... /home/judge/data/code/main.csproj を復元しました (103 ms)。 MSBuild のバージョン 17.9.6+a4ecab324 (.NET) main -> /home/judge/data/code/bin/Release/net8.0/main.dll main -> /home/judge/data/code/bin/Release/net8.0/publish/
ソースコード
using System; using System.Collections.Generic; using System.Linq; using System.IO; using System.Text; using System.Numerics; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Diagnostics; using static System.Math; using static System.Array; using static AtCoder.Cout; using static AtCoder.Tool; namespace AtCoder { class AC { const int INF = int.MaxValue / 2; const long SINF = long.MaxValue / 3; static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 }; static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 }; static void Main(string[] args) { var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw); /*var th = new Thread(Run, 1 << 26); th.Start(); th.Join();*/ Run(); Console.Out.Flush(); } static void Run() { int Testcase = 1; //Testcase = Cin.Int; for (var testcase_id = 0; testcase_id < Testcase; testcase_id++) { Solve(testcase_id); } } static void Solve(int testcase_id) { int N = Cin.Int; var A = Cin.ReadSplitInt; var B = Cin.ReadSplitInt; var Z = Cin.ReadSplitInt; var ida = new int[N]; var idb = new int[N]; for(var i = 0; i < N; i++) { A[i]--;B[i]--; Z[i]--; ida[A[i]] = i; idb[B[i]] = i; } //並列二分探索 var pos_left = new int[N]; var l = new int[N]; var r = new int[N]; for(var i = 0; i < N; i++) { l[i] = -1;r[i] = N; } var mid = new Queue<int>[N]; for (var i = 0; i < N; i++) mid[i] = new Queue<int>(); for(var _ = 0; _ < 17; _++) { // mid[i] : k = i で判定を行うペア番号の集合 for (var i = 0; i < N; i++) if (r[i] - l[i] > 1) mid[(l[i] + r[i]) / 2].Enqueue(i); var ufa = new DSU_AB(N); var ufb = new DSU_AB(N); for (var k = 0; k < N; k++) { int ia = ida[k], ib = idb[k]; if (0 < ia && A[ia - 1] <= k) ufa.Unite(ia - 1, ia); if (ia + 1 < N && A[ia + 1] <= k) ufa.Unite(ia, ia + 1); if (0 < ib && B[ib - 1] <= k) ufb.Unite(ib - 1, ib); if (ib + 1 < N && B[ib + 1] <= k) ufb.Unite(ib, ib + 1); while(mid[k].Any()) { int j = mid[k].Dequeue(); //この k の値において (j, Z_j) を同じ位置に配置することはできるか? if (ufa.Right(ida[j]) < ufb.Left(idb[Z[j]]) || ufb.Right(idb[Z[j]]) < ufa.Left(ida[j])) { l[j] = k; } else { r[j] = k; pos_left[j] = Max(ufa.Left(ida[j]), ufb.Left(idb[Z[j]])); } } } } for (var i = 0; i < N; i++) mid[r[i]].Enqueue(i); //答えを求める var ufi = new DSU_Idx(N); var less_k = new int[N]; for(var k = 0; k < N; k++) { int ia = ida[k], ib = idb[k]; less_k[ia]++;less_k[ib]++; if (less_k[ia] == 2) { if (0 < ia && less_k[ia - 1] == 2) ufi.Unite(ia - 1, ia); if (ia + 1 < N && less_k[ia + 1] == 2) ufi.Unite(ia, ia + 1); } if (less_k[ib] == 2) { if (0 < ib && less_k[ib - 1] == 2) ufi.Unite(ib - 1, ib); if (ib + 1 < N && less_k[ib + 1] == 2) ufi.Unite(ib, ib + 1); } foreach(var i in mid[k]) { ufi.Add_Pair(pos_left[i]); } OutL(ufi.Score); } } } public class DSU_AB { private int n; private int[] par_size; private int[] left; private int[] right; // par_size[i] = sizeof(i) (par_size[i] < 0) // parent(i) (par_size[i] >= 0) public DSU_AB(int size) { n = size; par_size = new int[n]; left = new int[n]; right = new int[n]; for (var i = 0; i < n; i++) { par_size[i] = -1; left[i] = right[i] = i; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Root(int v) { if (par_size[v] < 0) return v; while (par_size[par_size[v]] >= 0) { (v, par_size[v]) = (par_size[v], par_size[par_size[v]]); } return par_size[v]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int SizeOf(int v) => -par_size[Root(v)]; public void Unite(int u, int v) { int ru = Root(u), rv = Root(v); if (ru == rv) return; if (par_size[ru] > par_size[rv]) { par_size[rv] += par_size[ru]; par_size[ru] = rv; left[rv] = Min(left[rv], left[ru]); right[rv] = Max(right[rv], right[ru]); } else { par_size[ru] += par_size[rv]; par_size[rv] = ru; left[ru] = Min(left[ru], left[rv]); right[ru] = Max(right[ru], right[rv]); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Same(int u, int v) => Root(u) == Root(v); [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Left(int v) => left[Root(v)]; [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Right(int v) => right[Root(v)]; } public class DSU_Idx { private int n; private int[] par_size; private int[] num_pair; public int Score; // par_size[i] = sizeof(i) (par_size[i] < 0) // parent(i) (par_size[i] >= 0) public DSU_Idx(int size) { n = size; par_size = new int[n]; num_pair = new int[n]; Score = 0; for (var i = 0; i < n; i++) { par_size[i] = -1; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Root(int v) { if (par_size[v] < 0) return v; while (par_size[par_size[v]] >= 0) { (v, par_size[v]) = (par_size[v], par_size[par_size[v]]); } return par_size[v]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int SizeOf(int v) => -par_size[Root(v)]; // unite, num_pair更新時にScoreを差分更新する public void Unite(int u, int v) { int ru = Root(u), rv = Root(v); if (ru == rv) return; Score -= (Sub_score(ru) + Sub_score(rv)); if (par_size[ru] > par_size[rv]) { par_size[rv] += par_size[ru]; par_size[ru] = rv; num_pair[rv] += num_pair[ru]; Score += Sub_score(rv); } else { par_size[ru] += par_size[rv]; par_size[rv] = ru; num_pair[ru] += num_pair[rv]; Score += Sub_score(ru); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add_Pair(int v) { Score -= Sub_score(v); num_pair[Root(v)]++; Score += Sub_score(v); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Sub_score(int v) => Min(-par_size[Root(v)], num_pair[Root(v)]); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Same(int u, int v) => Root(u) == Root(v); } static class Cin { public static string[] ReadSplit => Console.ReadLine().Split(); public static int[] ReadSplitInt => ConvertAll(ReadSplit, int.Parse); public static long[] ReadSplitLong => ConvertAll(ReadSplit, long.Parse); public static double[] ReadSplit_Double => ConvertAll(ReadSplit, double.Parse); public static string Str => Console.ReadLine(); public static int Int => int.Parse(Console.ReadLine()); public static long Long => long.Parse(Console.ReadLine()); public static double Double => double.Parse(Console.ReadLine()); public static T Conv<T>(string input) { return (T)Convert.ChangeType(input, typeof(T)); } public static void Scanf<T>(out T a) => a = Conv<T>(Console.ReadLine()); public static void Scanf<T, U>(out T a, out U b) { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); } public static void Scanf<T, U, V>(out T a, out U b, out V c) { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); } public static void Scanf<T, U, V, W>(out T a, out U b, out V c, out W d) { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); } public static void Scanf<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e) { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); e = Conv<X>(q[4]); } } static class Cout { public static void OutL(object s) => Console.WriteLine(s); public static void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s)); public static void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s)); public static void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s)); public static void Out_One(object s) => Console.Write($"{s} "); public static void Out_One(object s, string sep) => Console.Write($"{s}{sep}"); public static void Endl() => Console.WriteLine(); } public static class Tool { static public void Initialize<T>(ref T[] array, T initialvalue) { array = ConvertAll(array, x => initialvalue); } static public void Swap<T>(ref T a, ref T b) { T keep = a; a = b; b = keep; } static public void Display<T>(T[,] array2d, int n, int m) { for (var i = 0; i < n; i++) { for (var j = 0; j < m; j++) { Console.Write($"{array2d[i, j]} "); } Console.WriteLine(); } } static public int GcdI(int a, int b) { if (a == 0 || b == 0) return Max(a, b); return a % b == 0 ? b : GcdI(b, a % b); } static public long Gcd(long a, long b) { if (a == 0 || b == 0) return Max(a, b); return a % b == 0 ? b : Gcd(b, a % b); } static public long Lcm(long a, long b) => a / Gcd(a, b) * b; static public int LcmI(int a, int b) => (a == 0 || b == 0) ? Max(a, b) : a / GcdI(a, b) * b; static public long ExtGcd(long a, long b, ref long x, ref long y) { // ax + by = gcd(a,b) なる x,y を求める // return gcd(a,b) if (b == 0) { x = 1; y = 0; return a; } long d = ExtGcd(b, a % b, ref y, ref x); y -= a / b * x; return d; } static public long LPow(int a, int b) => (long)Pow(a, b); static public bool Bit(long x, int dig) => ((1L << dig) & x) != 0; static public int Sig(long a) => a == 0 ? 0 : (int)(a / Abs(a)); static public long F_mp(long x, long n, long mod) => n == 0 ? (1 % mod) : (n % 2 == 0 ? F_mp((x * x) % mod, n >> 1, mod) : (x * F_mp(x, n - 1, mod)) % mod); static public long F_inv(long x, long mod) => F_mp(x, mod - 2, mod); static public decimal DSqrt(decimal x, decimal epsilon = 0.0M) { if (x < 0) throw new OverflowException("Cannot calculate square root from a negative number"); decimal current = (decimal)Math.Sqrt((double)x), previous; do { previous = current; if (previous == 0.0M) return 0; current = (previous + x / previous) / 2; } while (Math.Abs(previous - current) > epsilon); return current; } } }