TCO2016R3AEasy ParenthesesAndPermutation

想定解が賢すぎる.

問題概要(原文)

以下の制約を満たす $2N$ 文字の(validな)括弧列 $s,t$ は存在するか?存在するなら一例を示せ.

  • $s_i = t_{p_i}$ を満たす

考察

validな括弧列 $x$ の条件とは以下を満たす

  • '(' を $1$ ,')' を $-1$ に置き換える.
  • $x_1 + x_2 + \ldots + x_i \geq 0$
  • $x_1+ x_2 + \ldots + x_{2N} = 0$

これは以下のように言い換えられる

  • $i$ 文字目までに少なくとも '(' が $\frac{i+1}{2}$ 個ある
  • $2N$ 文字目の時点で '(' と ')' がそれぞれ $N$ 個ある

条件を満たす $s$ を一つ構築することにする. 初め,全ての文字を ')' ということにする.$2k + 1 (0 \leq k)$ 文字目の時点で $s_i = $ ')' $(1 \leq i \leq 2k+1)$ であるような $i$ を一つ選んで, '(' を ')' に置換できる. これをやるだけで,validな $s$ を構築できる.

このとき,どのような $i$ を選ぶのが最適かを考える. $p_i$ が最小のものを選ぶのが良いことが分かる(何故なら括弧列を作る際になるべく '(' を左側に寄せて損することはないので).

こうしてできた $t$ がvalidかどうか判定すればよい.計算量は $O(NlogN)$

ソースコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
public class ParenthesesAndPermutation
{
    public string getSequence(int[] p)
    {
        var n = p.Length;
        var s = new char[n];
        var t = new char[n];
        for (int i = 0; i < n; i++)
            s[i] = t[i] = ')';
        var set = new SortedSet<int>();
        for (int i = 0; i < n; i++)
        {
            set.Add(p[i] * n + i);
            if (i % 2 == 0)
            {
                var min = set.Min;
                set.Remove(min);
                var ii = min % n;
                var jj = min / n;
                s[ii] = t[jj] = '(';
            }
        }
        var v = 0;
        foreach (var x in t)
        {
            if (x == '(') v++;
            else v--;
            if (v < 0) return "Impossible";
        }
        return new string(s);
    }
}

コメント

  • 想定解,言われると当たり前なのに気づけないし,面白い問題だと思う