結果

問題 No.1698 Face to Face
ユーザー eSeFeSeF
提出日時 2021-06-14 00:59:29
言語 C#
(.NET 8.0.203)
結果
AC  
実行時間 890 ms / 5,000 ms
コード長 11,337 bytes
コンパイル時間 17,160 ms
コンパイル使用メモリ 147,528 KB
実行使用メモリ 217,772 KB
最終ジャッジ日時 2023-09-26 15:37:44
合計ジャッジ時間 32,870 ms
ジャッジサーバーID
(参考情報)
judge13 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 58 ms
29,876 KB
testcase_01 AC 59 ms
29,936 KB
testcase_02 AC 57 ms
30,104 KB
testcase_03 AC 465 ms
74,516 KB
testcase_04 AC 520 ms
77,404 KB
testcase_05 AC 702 ms
77,508 KB
testcase_06 AC 704 ms
81,840 KB
testcase_07 AC 683 ms
83,368 KB
testcase_08 AC 695 ms
84,128 KB
testcase_09 AC 703 ms
82,412 KB
testcase_10 AC 525 ms
79,616 KB
testcase_11 AC 767 ms
73,968 KB
testcase_12 AC 804 ms
73,592 KB
testcase_13 AC 57 ms
29,936 KB
testcase_14 AC 57 ms
32,216 KB
testcase_15 AC 890 ms
75,600 KB
testcase_16 AC 885 ms
74,692 KB
testcase_17 AC 879 ms
74,968 KB
testcase_18 AC 773 ms
85,872 KB
testcase_19 AC 761 ms
85,272 KB
testcase_20 AC 714 ms
85,016 KB
testcase_21 AC 393 ms
59,196 KB
testcase_22 AC 297 ms
47,552 KB
testcase_23 AC 115 ms
41,484 KB
testcase_24 AC 445 ms
53,888 KB
testcase_25 AC 834 ms
79,864 KB
testcase_26 AC 91 ms
35,392 KB
testcase_27 AC 224 ms
44,312 KB
testcase_28 AC 241 ms
42,428 KB
testcase_29 AC 184 ms
50,392 KB
testcase_30 AC 506 ms
67,268 KB
testcase_31 AC 387 ms
57,064 KB
testcase_32 AC 613 ms
68,176 KB
testcase_33 AC 612 ms
76,176 KB
testcase_34 AC 815 ms
78,004 KB
testcase_35 AC 58 ms
29,988 KB
testcase_36 AC 57 ms
29,764 KB
testcase_37 AC 57 ms
29,836 KB
testcase_38 AC 57 ms
29,992 KB
testcase_39 AC 57 ms
29,900 KB
testcase_40 AC 56 ms
30,076 KB
testcase_41 AC 56 ms
32,180 KB
testcase_42 AC 58 ms
32,028 KB
testcase_43 AC 56 ms
29,780 KB
testcase_44 AC 57 ms
29,920 KB
testcase_45 AC 606 ms
77,488 KB
testcase_46 AC 588 ms
75,780 KB
testcase_47 AC 711 ms
217,772 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
  Determining projects to restore...
  Restored /home/judge/data/code/main.csproj (in 135 ms).
.NET 向け Microsoft (R) Build Engine バージョン 17.0.0-preview-21470-01+cb055d28f
Copyright (C) Microsoft Corporation.All rights reserved.

  プレビュー版の .NET を使用しています。https://aka.ms/dotnet-core-preview をご覧ください
  main -> /home/judge/data/code/bin/Release/net6.0/main.dll
  main -> /home/judge/data/code/bin/Release/net6.0/publish/

ソースコード

diff #

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using System.Threading;
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 MOD = 1000000007;
        //const int MOD = 998244353;
        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 _ = 0; _ < Testcase; _++) Solve();
        }
        static void Solve()
        {
            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]] = idb[B[i]] = i;
            }

            var f = new int[N];//ペア i,Z_i が実現可能な最小の k
            var pt = new int[N];// k=f[i] において、ペアを配置できる代表点
            var l = new int[N];
            var r = new int[N];
            for (var i = 0; i < N; i++)
            {
                l[i] = -1;
                r[i] = N;
                pt[i] = -1;
            }
            var mids = new Queue<int>[N];
            for (var i = 0; i < N; i++) mids[i] = new Queue<int>();
            for (var _ = 0; _ < 18; _++)
            {
                for (var i = 0; i < N; i++) mids[(l[i] + r[i]) / 2].Enqueue(i);
                var ufa = new ExtUnionFind(N);
                var ufb = new ExtUnionFind(N);

                for (var k = 0; k < N; k++)
                {
                    int ia = ida[k];
                    int ib = idb[k];
                    if (ia - 1 >= 0 && A[ia - 1] <= k) ufa.Unite(ia, ia - 1);
                    if (ia + 1 < N && A[ia + 1] <= k) ufa.Unite(ia, ia + 1);
                    if (ib - 1 >= 0 && B[ib - 1] <= k) ufb.Unite(ib, ib - 1);
                    if (ib + 1 < N && B[ib + 1] <= k) ufb.Unite(ib, ib + 1);

                    while(mids[k].Any())
                    {
                        var q = mids[k].Dequeue();
                        int la = ufa.Lef(ida[q]), ra = ufa.Rig(ida[q]);
                        int lb = ufb.Lef(idb[Z[q]]), rb = ufb.Rig(idb[Z[q]]);

                        if (ra < lb || rb < la)
                        {
                            l[q] = k;
                        }
                        else
                        {
                            r[q] = k;
                            pt[q] = Max(la, lb);
                        }
                    }
                }
            }
            for (var i = 0; i < N; i++) f[i] = r[i];
            //OutL($"result:");
            //Out_Sep(f);
            //Out_Sep(pt);

            //OutL($"=========");

            var uf = new ExtUnionFind2(N);
            var pos = new List<int>[N];
            for (var i = 0; i < N; i++) pos[i] = new List<int>();
            for (var i = 0; i < N; i++) pos[f[i]].Add(i);
            var act = new int[N];
            for (var k = 0; k < N; k++)
            {
                act[ida[k]]++;
                if (act[ida[k]] == 2)
                {
                    int id = ida[k];
                    if (id > 0 && act[id - 1] == 2) uf.Unite(id, id - 1);
                    if (id + 1 < N && act[id + 1] == 2) uf.Unite(id, id + 1);
                }
                act[idb[k]]++;
                if (act[idb[k]] == 2)
                {
                    int id = idb[k];
                    if (id > 0 && act[id - 1] == 2) uf.Unite(id, id - 1);
                    if (id + 1 < N && act[id + 1] == 2) uf.Unite(id, id + 1);
                }

                foreach (var ok in pos[k])
                {
                    uf.Add_P(pt[ok]);
                }
                OutL(uf.Ans());
            }

        }
    }
    //区間右端と左端を管理
    public class ExtUnionFind
    {
        private int[] parent;
        private int[] rank;
        private int[] L;
        private int[] R;
        public ExtUnionFind(int n)
        {
            parent = new int[n];
            rank = new int[n];
            L = new int[n];
            R = new int[n];
            for (var i = 0; i < n; i++)
            {
                parent[i] = i;

                L[i] = i;
                R[i] = i;
            }
        }

        public int Root(int x)
        {
            return parent[x] == x ? x : parent[x] = Root(parent[x]);
        }

        public bool SameRoot(int x, int y)
        {
            return Root(x) == Root(y);
        }
        public void Unite(int x, int y)
        {
            x = Root(x);
            y = Root(y);
            if (x == y) { return; }
            if (rank[x] < rank[y])
            {
                parent[x] = y;

                L[y] = Min(L[x], L[y]);
                R[y] = Max(R[x], R[y]);
            }
            else
            {
                parent[y] = x;
                if (rank[x] == rank[y]) { rank[x]++; }

                L[x] = Min(L[x], L[y]);
                R[x] = Max(R[x], R[y]);
            }
        }
        public int Lef(int x) => L[Root(x)];
        public int Rig(int x) => R[Root(x)];
    }
    //サイズと属するペア数を管理
    public class ExtUnionFind2
    {
        private int[] parent;
        private int[] rank;
        private int[] size;
        private int[] P;
        private long ans;
        public ExtUnionFind2(int n)
        {
            parent = new int[n];
            rank = new int[n];
            size = new int[n];
            P = new int[n];
            ans = 0;
            for (var i = 0; i < n; i++)
            {
                parent[i] = i;
                size[i] = 1;
            }
        }

        public int Root(int x)
        {
            return parent[x] == x ? x : parent[x] = Root(parent[x]);
        }

        public bool SameRoot(int x, int y)
        {
            return Root(x) == Root(y);
        }

        public void Unite(int x, int y)
        {
            x = Root(x);
            y = Root(y);
            if (x == y) { return; }
            ans -= Score(x) + Score(y);

            if (rank[x] < rank[y])
            {
                parent[x] = y;
                size[y] += size[x];
                P[y] += P[x];
            }
            else
            {
                parent[y] = x;
                if (rank[x] == rank[y]) { rank[x]++; }
                size[x] += size[y];
                P[x] += P[y];
            }

            ans += Score(x);
        }

        public int SizeOf(int x)
        {
            return size[Root(x)];
        }
        public void Add_P(int x)
        {
            ans -= Score(x);
            P[Root(x)]++;
            ans += Score(x);
        }
        public int Score(int x) => Min(size[Root(x)], P[Root(x)]);
        public long Ans() => ans;
    }
    public struct Edge
    {
        public int from, to;
        public long w;
        public double dw;
        public Edge(int to, long weight) { this.to = to; w = weight; from = -1; dw = -1; }
        public Edge(int from, int to, long weight) { this.from = from; this.to = to; w = weight; dw = -1; }
        public Edge(int to, double weight) { this.to = to; from = -1; w = -1; dw = weight; }
    }
    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)
        {
            /*if (typeof(T).Equals(typeof(ModInt)))
            {
                return (T)(dynamic)(long.Parse(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 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 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));
    }
}
0