結果

問題 No.2080 Simple Nim Query
ユーザー lam6er
提出日時 2025-03-31 17:50:51
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 2,237 ms / 3,000 ms
コード長 5,864 bytes
コンパイル時間 162 ms
コンパイル使用メモリ 82,280 KB
実行使用メモリ 168,048 KB
最終ジャッジ日時 2025-03-31 17:52:00
合計ジャッジ時間 12,459 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 8
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys

def main():
    sys.setrecursionlimit(1 << 25)
    input = sys.stdin.read().split()
    ptr = 0
    N = int(input[ptr]); ptr +=1
    Q = int(input[ptr]); ptr +=1
    A = list(map(int, input[ptr:ptr+N]))
    ptr +=N
    
    class MaxSegmentTree:
        def __init__(self, data):
            self.n = len(data)
            self.size = 1 << (self.n -1).bit_length()
            self.tree = [ -float('inf') ] * (2 * self.size)
            for i in range(self.n):
                self.tree[self.size +i] = data[i]
            for i in range(self.size-1, 0, -1):
                self.tree[i] = max(self.tree[2*i], self.tree[2*i+1])
        
        def update(self, pos, val):
            pos += self.size
            self.tree[pos] = val
            pos >>=1
            while pos >=1:
                new_val = max(self.tree[2*pos], self.tree[2*pos +1])
                if self.tree[pos] == new_val:
                    break
                self.tree[pos] = new_val
                pos >>=1
        
        def query(self, l, r):
            res = -float('inf')
            l += self.size
            r += self.size
            while l <= r:
                if l %2 ==1:
                    res = max(res, self.tree[l])
                    l +=1
                if r %2 ==0:
                    res = max(res, self.tree[r])
                    r -=1
                l >>=1
                r >>=1
            return res
    
    class RightmostGt1SegmentTree:
        def __init__(self, data):
            self.n = len(data)
            self.size = 1 << (self.n -1).bit_length()
            self.tree = [ -1 ] * (2 * self.size)
            for i in range(self.n):
                self.tree[self.size +i] = i if data[i] >1 else -1
            for i in range(self.size-1, 0, -1):
                left = self.tree[2*i]
                right = self.tree[2*i+1]
                self.tree[i] = right if right !=-1 else left
        
        def update(self, pos, val):
            pos_in_tree = self.size + pos
            self.tree[pos_in_tree] = pos if val >1 else -1
            pos_in_tree >>=1
            while pos_in_tree >=1:
                left = self.tree[2*pos_in_tree]
                right = self.tree[2*pos_in_tree+1]
                new_val = right if right !=-1 else left
                if self.tree[pos_in_tree] == new_val:
                    break
                self.tree[pos_in_tree] = new_val
                pos_in_tree >>=1
        
        def query(self, l, r):
            def _query(a, b, node, node_l, node_r):
                if a > node_r or b < node_l:
                    return -1
                if a <= node_l and node_r <=b:
                    return self.tree[node]
                mid = (node_l + node_r) //2
                right_res = _query(a, b, 2*node+1, mid+1, node_r)
                if right_res !=-1:
                    return right_res
                return _query(a, b, 2*node, node_l, mid)
            return _query(l, r, 1, 0, self.size -1)
    
    class Count1SegmentTree:
        def __init__(self, data):
            self.n = len(data)
            self.size = 1 << (self.n -1).bit_length()
            self.tree = [0]*(2*self.size)
            for i in range(self.n):
                self.tree[self.size +i] = 1 if data[i] ==1 else 0
            for i in range(self.size-1, 0, -1):
                self.tree[i] = self.tree[2*i] + self.tree[2*i +1]
        
        def update(self, pos, val):
            pos_in_tree = self.size + pos
            new_val = 1 if val ==1 else 0
            if self.tree[pos_in_tree] == new_val:
                return
            self.tree[pos_in_tree] = new_val
            pos_in_tree >>=1
            while pos_in_tree >=1:
                new_sum = self.tree[2*pos_in_tree] + self.tree[2*pos_in_tree +1]
                if self.tree[pos_in_tree] == new_sum:
                    break
                self.tree[pos_in_tree] = new_sum
                pos_in_tree >>=1
        
        def query(self, l, r):
            res =0
            l += self.size
            r += self.size
            while l <=r:
                if l %2 ==1:
                    res += self.tree[l]
                    l +=1
                if r %2 ==0:
                    res += self.tree[r]
                    r -=1
                l >>=1
                r >>=1
            return res
    
    # Convert the A to 0-based index
    max_tree = MaxSegmentTree(A)
    data_gt1 = [A[i] for i in range(N)]
    rightmost_tree = RightmostGt1SegmentTree(data_gt1)
    count1_tree = Count1SegmentTree(A)
    
    for _ in range(Q):
        T = int(input[ptr]); ptr +=1
        X = int(input[ptr])-1; ptr +=1 # 0-based
        Y = int(input[ptr]); ptr +=1
        
        if T ==1:
            # update A[X] to Y
            pos = X
            val = Y
            A[pos] = val
            max_tree.update(pos, val)
            rightmost_tree.update(pos, val)
            count1_tree.update(pos, val)
        else:
            # query [X..Y-1] (original X is 1-based, Y is also 1-based)
            # convert to 0-based range X..Y-1
            L = X
            R = Y -1 # because Y in input is 1-based. ex: input 1 2 -> 0-based 0 to 1
            max_val = max_tree.query(L, R)
            if max_val ==1:
                length = R - L +1
                if length %2 ==1:
                    print("F")
                else:
                    print("S")
            else:
                pos = rightmost_tree.query(L, R)
                start = pos +1
                end = R
                if start > end:
                    trail_ones =0
                else:
                    trail_ones = count1_tree.query(start, end)
                if trail_ones %2 ==0:
                    print("F")
                else:
                    print("S")

if __name__ == "__main__":
    main()
0