結果

問題 No.1698 Face to Face
ユーザー eSeFeSeF
提出日時 2020-12-15 22:15:21
言語 C#(csc)
(csc 3.9.0)
結果
AC  
実行時間 1,069 ms / 5,000 ms
コード長 11,337 bytes
コンパイル時間 2,829 ms
コンパイル使用メモリ 114,644 KB
実行使用メモリ 75,536 KB
最終ジャッジ日時 2023-09-26 15:37:00
合計ジャッジ時間 31,123 ms
ジャッジサーバーID
(参考情報)
judge14 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 62 ms
21,592 KB
testcase_01 AC 60 ms
19,320 KB
testcase_02 AC 62 ms
21,532 KB
testcase_03 AC 660 ms
67,348 KB
testcase_04 AC 701 ms
73,404 KB
testcase_05 AC 882 ms
70,716 KB
testcase_06 AC 884 ms
71,948 KB
testcase_07 AC 873 ms
72,408 KB
testcase_08 AC 874 ms
73,920 KB
testcase_09 AC 900 ms
73,752 KB
testcase_10 AC 747 ms
73,604 KB
testcase_11 AC 953 ms
73,264 KB
testcase_12 AC 986 ms
70,180 KB
testcase_13 AC 61 ms
21,520 KB
testcase_14 AC 62 ms
21,432 KB
testcase_15 AC 1,061 ms
70,260 KB
testcase_16 AC 1,069 ms
70,472 KB
testcase_17 AC 1,067 ms
68,632 KB
testcase_18 AC 916 ms
63,608 KB
testcase_19 AC 912 ms
62,180 KB
testcase_20 AC 854 ms
64,268 KB
testcase_21 AC 449 ms
51,432 KB
testcase_22 AC 354 ms
48,836 KB
testcase_23 AC 136 ms
34,680 KB
testcase_24 AC 521 ms
56,088 KB
testcase_25 AC 977 ms
63,252 KB
testcase_26 AC 105 ms
30,692 KB
testcase_27 AC 259 ms
44,476 KB
testcase_28 AC 279 ms
45,708 KB
testcase_29 AC 218 ms
44,472 KB
testcase_30 AC 653 ms
57,572 KB
testcase_31 AC 460 ms
49,252 KB
testcase_32 AC 753 ms
61,528 KB
testcase_33 AC 748 ms
59,220 KB
testcase_34 AC 999 ms
71,132 KB
testcase_35 AC 62 ms
21,536 KB
testcase_36 AC 62 ms
21,512 KB
testcase_37 AC 61 ms
21,532 KB
testcase_38 AC 61 ms
23,488 KB
testcase_39 AC 62 ms
21,484 KB
testcase_40 AC 62 ms
23,660 KB
testcase_41 AC 61 ms
21,528 KB
testcase_42 AC 62 ms
23,480 KB
testcase_43 AC 64 ms
21,504 KB
testcase_44 AC 60 ms
21,428 KB
testcase_45 AC 779 ms
68,904 KB
testcase_46 AC 783 ms
72,244 KB
testcase_47 AC 923 ms
75,536 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc)
Copyright (C) Microsoft Corporation. All rights reserved.

ソースコード

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