3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ABC247A~DをPythonで解く!

Last updated at Posted at 2022-04-10

はじめに

ABC247に参戦しA~D問題を完答できたためシェアします!

A Move Right

問題

0101のような0,1で作られる4文字の文字列を右に1つずらした場合の文字列を求めよ(意訳)

解答

左から3つ目までを取り出し左に0をつければよいです。
0101 → 0010

S = input()
print('0'+S[:3])

B Unique Nicknames

問題

N人、人がおりi番目の人の名字・名前は$s_i,t_i$で与えられます。
N人のニックネームを次のルールで名付けます。
1.それぞれのニックネームは名字$s_i$か名前$t_i$
2.他の人の名字・名前に無いニックネームを名付けなければならない
このルールのもと全員にニックネームを付けられるか

解答

ルール2から、それぞれの人は唯一の名字・名前をもっていないとニックネームをつけてもらえません。
したがって、名字・名前をカウントし唯一の名字と名前を持たない人がいる場合Noとなります。
また、ルール2が満たされていればルール1を満たすように選べます。
注意点として、名字と名前が同じ場合にカウントを重複させないようにしましょう。

from collections import defaultdict
N = int(input())
name = [input().split() for _ in range(N)]
named = defaultdict(int)
for i in range(N):
    if name[i][0] == name[i][1]:
        named[name[i][0]] += 1
    else:
        named[name[i][0]] += 1
        named[name[i][1]] += 1
for i,j in name:
    if named[i] == 1 or named[j] == 1:
        continue
    else:
        print('No')
        break
else:
    print('Yes')

C 1 2 1 3 1 2 1

問題

$S_1=1,\ S_n=S_{n-1}\ n \ S_{n-1} \ (n=2,3,...,N)$を満たす文字列を出力してください。

例 (N=3)
$S_1=1$
$S_2=S_1 \ 2 \ S_1 = 1 \ 2 \ 1$
$S_3=S_2 \ 3 \ S_2 = 1 \ 2 \ 1 \ 3 \ 1 \ 2 \ 1 $

解答

再帰関数を用いて$S_n = S_{n-1} \ n \ S_{n-1}$を実行したらよいです。
ただし$n=1$のときは1を返します。

import sys
sys.setrecursionlimit(100000)

def Num(num):
    if num == 1:
        return '1'
    return Num(num-1) + ' ' + str(num) + ' ' + Num(num-1)
N = int(input())
print(Num(N))

D Cylinder

問題

筒にボールを入れる。もしくは出すQ回のクエリを処理してください。
クエリは
1 x c
2 c
で与えられ先頭が1の場合は筒にボールを入れる。2の場合は筒の左からボールを出します。
ただし、出す処理において筒に入っているボールより多く取り出すことはありません。

解答

筒に入っているボールより多く取り出すことはないため、筒にボールをすべて入れてから取り出す処理をしても逐次取り出す場合と変わりません。そこで、
・ボールの数字をもつ配列ball
・ボールの累積個数を持つ配列num
・ボールの数字×ボールの個数の累積和をもつ配列Sum
・取り出すボールの累積和を持つ配列queries
を用意し、まずクエリを保存します。
例えば、
4
1 2 2
1 3 3
2 3
1 0 2
2 3
のクエリに対してそれぞれの配列は
ball = [2,3,0]
num = [2,5,7]
Sum = [4,13,13]
queries = [3,6]

なぜnum,Sum,queriesを累積和にしたか

以下の図のように、各処理ごとに合計値を計算するため累積和の配列を用意しています。
1回目の取り出し

2回目の取り出し

n回目の取り出し

iをどう求めるか

num[i] < n回目までに取り出されたボールの数(queries[n]) <= num[i]となるiを二分探索により求めます。
numは累積和であり、昇順となっているため二分探索が有効です。

求めたiを用いて上図のようにn回目に取り出す合計値を求めれば終了です。

def bisect(x):
    ok = len(num)
    ng = -1
    while ok-ng>1:
        mid = (ok+ng)//2
        if x<= num[mid]:
            ok = mid
        else:
            ng = mid
    if x < num[ok]:
        return Sum[ok]-ball[ok]*(num[ok]-x)
    else:      
        return Sum[ok]

Q = int(input())
ball = []
num = [0]
Sum = [0]
queries = [0]
for _ in range(Q):
    query = list(map(int, input().split()))
    if query[0] == 1:
        ball.append(query[1])
        Sum.append(Sum[-1]+query[1]*query[2])
        num.append(num[-1]+query[2])
    else:
        queries.append(queries[-1]+query[1])
num = num[1:]
Sum = Sum[1:]
queries = queries[1:]
pre = 0
for i in queries:
    q = bisect(i)
    ans = q-pre
    pre = q
    print(ans)
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?