結果

問題 No.1698 Face to Face
ユーザー eSeFeSeF
提出日時 2020-12-15 22:15:21
言語 C#(csc)
(csc 3.9.0)
結果
AC  
実行時間 914 ms / 5,000 ms
コード長 11,337 bytes
コンパイル時間 1,054 ms
コンパイル使用メモリ 117,392 KB
実行使用メモリ 79,228 KB
最終ジャッジ日時 2024-07-19 09:42:55
合計ジャッジ時間 24,388 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 28 ms
24,904 KB
testcase_01 AC 27 ms
25,012 KB
testcase_02 AC 27 ms
25,156 KB
testcase_03 AC 592 ms
74,936 KB
testcase_04 AC 628 ms
78,976 KB
testcase_05 AC 780 ms
74,228 KB
testcase_06 AC 769 ms
76,668 KB
testcase_07 AC 775 ms
74,080 KB
testcase_08 AC 764 ms
75,368 KB
testcase_09 AC 774 ms
77,440 KB
testcase_10 AC 644 ms
77,432 KB
testcase_11 AC 837 ms
73,868 KB
testcase_12 AC 841 ms
73,396 KB
testcase_13 AC 27 ms
24,908 KB
testcase_14 AC 27 ms
25,272 KB
testcase_15 AC 898 ms
70,332 KB
testcase_16 AC 914 ms
70,084 KB
testcase_17 AC 908 ms
68,076 KB
testcase_18 AC 783 ms
67,020 KB
testcase_19 AC 772 ms
64,976 KB
testcase_20 AC 869 ms
65,792 KB
testcase_21 AC 430 ms
53,212 KB
testcase_22 AC 288 ms
50,300 KB
testcase_23 AC 95 ms
36,256 KB
testcase_24 AC 422 ms
57,624 KB
testcase_25 AC 841 ms
70,956 KB
testcase_26 AC 64 ms
32,316 KB
testcase_27 AC 209 ms
48,004 KB
testcase_28 AC 226 ms
49,080 KB
testcase_29 AC 173 ms
46,124 KB
testcase_30 AC 530 ms
58,148 KB
testcase_31 AC 379 ms
54,672 KB
testcase_32 AC 629 ms
65,192 KB
testcase_33 AC 659 ms
63,168 KB
testcase_34 AC 882 ms
73,272 KB
testcase_35 AC 26 ms
24,876 KB
testcase_36 AC 28 ms
26,948 KB
testcase_37 AC 28 ms
25,132 KB
testcase_38 AC 29 ms
25,268 KB
testcase_39 AC 27 ms
26,824 KB
testcase_40 AC 27 ms
25,136 KB
testcase_41 AC 26 ms
26,932 KB
testcase_42 AC 28 ms
27,188 KB
testcase_43 AC 27 ms
25,024 KB
testcase_44 AC 28 ms
24,896 KB
testcase_45 AC 703 ms
70,668 KB
testcase_46 AC 696 ms
77,844 KB
testcase_47 AC 793 ms
79,228 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