備忘録

徒然なるままに。

競プロ典型:Score Sum Queries

うっかり投稿が途切れてしまった。
一先ず、解き切れていなくても書いたコードを上げていこうと思う。
考察等はモノによっては後日改めて投稿する形にして毎日コードをどんどん書いていこうと思う。継続は何とやら。

しばらくはAtCoderの競プロ典型を解いていく。

今日はScore Sum Queries。星2から解いていこうかと。この星は難易度を示しているという解釈でいいんだろうか?

自分のコード

N = int(input())
l = [list(map(int, input().split())) for l in range(N)]

Q = int(input())
q = [list(map(int, input().split())) for q in range(Q)]

for i in range(len(q)):
    min_num = q[i][0]
    max_num = q[i][1]
    
    new_list = l[min_num-1:max_num]

    score_first = 0
    score_second = 0
    
    for j in range(len(new_list)):
        if new_list[j][0] == 1:
            score_first += new_list[j][1]
        else:
            score_second += new_list[j][1]
    
    print(score_first,score_second)

脳筋コードである。ただでさえPythonでforを回すことは憚られるのに二重で回すもんだから勿論TLEを食らうわけである。一応テストはすべてクリアしている。
やっていること自体はそんなに難しいことではなくQを読み込みながらQの範囲に合わせてlistを組みなおしてクラスごとにスコアを足し合わせている。
このforの二重ループはどうやって解消すべきか今回は他の方々のコードから勉強したい。


コード1:

import sys
input = lambda: sys.stdin.readline().rstrip()
# sys.setrecursionlimit(10**6)
 
 
N = int(input())
class1 = []
class2 = []
for i in range(N):
    c, p = map(int, input().split())
    if c == 1:
        class1.append(p)
        class2.append(0)
    else:
        class1.append(0)
        class2.append(p)
 
cumsum1 = [0]
cumsum2 = [0]
for i in range(N):
    cumsum1.append(cumsum1[-1]+class1[i])
    cumsum2.append(cumsum2[-1]+class2[i])
 
Q = int(input())
for _ in range(Q):
    l, r = map(int, input().split())
    l -= 1
    print(cumsum1[r]-cumsum1[l], cumsum2[r]-cumsum2[l])

Submission #40072295 - 競プロ典型 90 問 より

コード2:

n=int(input())
 
s1=[0]
s2=[0]
t1=0
t2=0
 
for i in range(n):
    c,p=map(int,input().split())
    if c==1:
        t1+=p
    else:
        t2+=p
    s1.append(t1)
    s2.append(t2)
 
q=int(input())
for i in range(q):
    l,r=map(int,input().split())
    print(s1[r]-s1[l-1], s2[r]-s2[l-1])

Submission #40169579 - 競プロ典型 90 問より

直近提出されたコードからそれぞれ実行時間が最も短いモノとコード長が短いモノを引用させて頂いた。
そもそも冷静に考えて入力をとる段階から処理をすればここまでループがかさばらないんだった(いつかも似たような反省をした気がする。。)。
内包表記しているだけで標準入力をとっている部分もループしているのだった。これを分けずに処理をその中でもすることでより早くなりそうだ。

二つ引用したがやっていることは同じでクラスごとに一人ずつ得点の和を学籍番号順にリストに入れていって最後にQで指定された学籍番号の上下で差をとることで、指定された学籍番号内の生徒の得点の総和を出力している。

自分のコードと比較すると、自分の者にはやはりループ削減の意識と総和計算の工夫が足りないことが分かる。