Yuulis.log

トンネルを抜けるとそこは参照エラーであった。

【AtCoder】ABC 360 B - Vertical Reading | 茶コーダーが解くAtCoder

atcoder.jp

実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 78

問題概要

英小文字からなる文字列  S, T が与えられる。次の条件を満たす  1 \leq c \leq w < |S| となる整数の組  (c, w) が存在するかを判定せよ。ここで、  |S| S の長さを表す。

  • 条件 :  S を先頭から  w 文字ごとに区切ったとき、長さが  c 以上の文字列の  c 番目の文字を順番に連結した文字列が  T と一致する。

制約

  •  1 \leq |T| \leq |S| \leq 100

考察

 c, w ともに  100 以下なので、2重ループを用いて条件の通りに全探索してしまおう。

実装のポイントとして、「 w 文字ごとに区切る」という操作と「区切った文字列の  c 番目を連結する」という操作の2つを同時に行うため、  S について 「 c 文字目から始めて  w 文字目を順に取り出していく」という方針を取っている。

コード

#include <bits/stdc++.h>
using namespace std;

#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)

// ======================================== //

int main()
{
    string S, T;
    cin >> S >> T;

    rep(w, 0, S.size()) rep(c, 0, w)
    {
        string temp = "";
        for (int i = c; i < S.size(); i += w)
        {
            temp += S[i];
        }

        if (temp == T)
        {
            cout << "Yes" << endl;
            return 0;
        }
    }

    cout << "No" << endl;
    return 0;
}

atcoder.jp

実装時間: 5分

【AtCoder】ABC 360 A - A Healthy Breakfast | 茶コーダーが解くAtCoder

atcoder.jp

実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 19

問題概要

各文字がR, M, Sのいずれかである文字列  S が与えられる。RMよりも左にあるかを判定せよ。

制約

  •  S の長さは  3 であり、R, M, Sが1文字ずつ含まれる。

考察

for文で  S 内にRMが現れるインデックス( それぞれr, mとした )を記録しておき、  r < m であるかを判定すればよい。

コード

#include <bits/stdc++.h>
using namespace std;

// ======================================== //

int main()
{
    string S;
    cin >> S;

    int r = -1, m = -1;
    rep(i, 0, 3)
    {
        if (S[i] == 'R')
            r = i;
        if (S[i] == 'M')
            m = i;
    }

    if (r < m)
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}

atcoder.jp

実装時間: 5分以内

【AtCoder】ABC 361 A - Insert | 茶コーダーが解くAtCoder

atcoder.jp

実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 15

問題概要

長さ  N の整数列  A と整数  K, X が与えられる。  A K 番目の要素の直後に  X を挿入した整数列を出力せよ。

制約

  • 入力はすべて整数。
  •  1 \leq K \leq X \leq 100
  •  1 \leq A_i, X \leq 100

考察

色々実装の方針がありそうだが、一番簡単なのはタイトルの通りvector::insertを使う方法だろう。

insertは第一引数に要素を挿入したい位置のイテレータ、第二引数に挿入したい要素を指定する。

cpprefjp.github.io

挿入の処理には線形時間かかるせいで使いどころがあまりないので存在を忘れがち。

コード

#include <bits/stdc++.h>
using namespace std;

#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)

// ======================================== //

int main()
{
    int N, K, X;
    cin >> N >> K >> X;
    vector<int> A(N);
    rep(i, 0, N) cin >> A[i];

    A.insert(A.begin() + K, X);

    for (auto &&a : A)
    {
        cout << a << " ";
    }
    cout << endl;
}

atcoder.jp

実装時間: 5分以内

【AtCoder】ABC 361 B - Intersection of Cuboids | 茶コーダーが解くAtCoder

atcoder.jp

実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 299

問題概要

 xyz 空間内において2点  (a, b, c), \, (d, e, f) を結ぶ線分を対角線とし、全ての面が  xy, yz, zx 平面上のいずれかに平行な直方体を  C(a, b, c, d, e, f) と書く。2つの直方体  C(a, b, c, d, e, f), \, C(g, h, i, j, k, l) が与えられるので、これらの共通部分の体積が正であるかを判定せよ。

制約

  • 入力はすべて整数。
  •  0 \leq a < d \leq 1000
  •  0 \leq b < e \leq 1000
  •  0 \leq c < f \leq 1000
  •  0 \leq g < j \leq 1000
  •  0 \leq h < k \leq 1000
  •  0 \leq i < l \leq 1000

考察

サンプルケース1のところに図が掲載されているので多少考えやすいが、やはり空間上で物事を考えると混乱しやすい。ここは次元を落として1次元の問題として次を考えてみよう。

  •  x 軸上に2点  (a), (b) を結ぶ線分を  l(a, b) と書く。2つの線分  l(a,b), \, l(c, d) が共通部分を持つか判定せよ ( a, b, c, d > 0) 。

これは絵を描いて  l(a, b) を固定したうえで  l(c, d) を左右に動かしてみればすぐに解決する。2つの線分の左側と右側の点それぞれに注目し、  x_1 = \max(a, c), \: x_2 = \min(b, d) としたとき、

  •  x_1 < x_2 \implies 共通部分を持つ
  •  x_1 \geq x_2 \implies 共通部分を持たない

と定式化できる。


同じことを  y, z 軸に対しても行えばよい。実装に関してはコードを参照のこと。

コード

#include <bits/stdc++.h>
using namespace std;

// ======================================== //

int main()
{
    int a, b, c, d, e, f, g, h, i, j, k, l;
    cin >> a >> b >> c >> d >> e >> f >> g >> h >> i >> j >> k >> l;

    int x1 = max(a, g);
    int y1 = max(b, h);
    int z1 = max(c, i);
    int x2 = min(d, j);
    int y2 = min(e, k);
    int z2 = min(f, l);

    if (x1 < x2 && y1 < y2 && z1 < z2)
    {
        cout << "Yes" << endl;
    }
    else
    {
        cout << "No" << endl;
    }
}

atcoder.jp

実装時間: 5分


幾何に関する問題、特に3次元のものはバグらせがちなのでめっちゃヒヤヒヤする。今回はすんなり解けてよかった...

【AtCoder】ABC 361 C - Make Them Narrow | 茶コーダーが解くAtCoder

atcoder.jp

実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 342

問題概要

長さ  A の数列が与えられる。  A の要素のうち任意の  K 個の要素を削除し、残りの要素をそのまま並べたものを数列  B とする。  (B \text{の最大値}) - B \text{の最小値} としてあり得る最小値を求めよ。

制約

  • 入力はすべて整数。
  •  1 \leq K < N \leq 2 \times 10^5
  •  1 \leq A_i \leq 10^9

考察

問題文に「順序を保って」とあるが、結局最小化をしなければいけないのでソートしても問題はない。

方針としては、次のようになる。

  1.  A を昇順ソートする。
  2. ある要素  A_i \: (1 \leq i \leq K + 1) を固定する。これが  B の最小値となる。
  3.  A_i から数えて  N - K - 1 個目の要素を見る。これが  B の最大値となる。 (  A の中で  A_i から  A_{i + (N-K-1)} の部分配列を取り出して  B とするイメージ)
  4.  A_{i+(N-K-1)} - A_i 1 \leq i \leq K + 1 で考えたときの最小値を出力する。

あとはこれを実装するだけ。

コード

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)

// ======================================== //

int main()
{
    int N, K;
    cin >> N >> K;
    vector<ll> A(N);
    rep(i, 0, N) cin >> A[i];

    sort(all(A));

    ll ans = INFL;

    rep(i, 0, K + 1)
    {
        ll temp = A[i + (N - K) - 1] - A[i];
        chmin(ans, temp);
    }

    cout << ans << endl;
}

atcoder.jp

実装時間: 20分