A. Submission Bait
https://codeforces.com/contest/1990/problem/A
博弈论
先选最大的有奇数个数量的数字,这样能保证对手后面怎么选,都有相同的可选
看有没有出现奇数个的元素即可
from collections import Counter
def check():
for i in c.values():
if i % 2 == 1:
return True
return False
t = int(input())
for _ in range(t):
n = int(input())
a = list(map(int, input().split()))
c = Counter(a)
if check():
print("YES")
else:
print("NO")
B. Array Craft
https://codeforces.com/contest/1990/problem/B
构造
题意,给定y<x,构造a数组,使从开头加到ax是最大的前缀和,从ay加到结尾是最大的后缀,a只能使用1和-1
发现前缀和后缀中间一定有重合的部分,将该部分设为1,这部分和至少为2,然后保证不会有更短的最大前缀,最大后缀,从y-1往前-1和1交替,从x+1往后-1和1交替,每两个可以抵消
t = int(input())
for _ in range(t):
n, x, y = map(int, input().split())
a = [0]*n
for i in range(y-1, x):
a[i] = 1
now = -1
for i in range(x, n):
a[i] = now
if now == 1:
now = -1
else:
now = 1
now = -1
for i in range(y-2, -1, -1):
a[i] = now
if now == 1:
now = -1
else:
now = 1
for ai in a:
print(ai, end=" ")
print()
C. Mad MAD Sum
https://codeforces.com/contest/1990/problem/C
题意,每次答案加上a数组的总和,每一次迭代将a每个元素更新为数组上一次该索引前出现两个以上的最大的数,直到a中所有元素都为0
思路:可以发现一个数出现两次后,若未出现更大的,后面都是以该数字为结果,且每次迭代,除最后一个最大值个数会减一,其他的数字只要仍有两个,下一次出现的数目不会改变,由此想到可以单独计算每个数字的贡献
存储每个数字在第一次迭代后的状态,每个元素计算作为最大值的左右位置和上一个最大值,
如果有数字只出现了一次,下一次迭代将不会出现,这时这个数字在之后的位置就会被上个出现两次以上的最大值替代,这里用dp思想,若上个最大值仍只出现一次,直接用上上个最大值即可
最后用等差数列计一下数,只出现一次的,计算下替代的元素
def cal(be, ct):
return (be+be-ct+1)*ct//2
t = int(input())
for _ in range(t):
n = int(input())
a = list(map(int, input().split()))
ct = [0]*(n+1)
lr = [[-1, -1, 0] for _ in range(n+1)]
ma = 0
for i in range(n):
if ct[a[i]] == 0:
ct[a[i]] += 1
elif ct[a[i]] == 1:
ct[a[i]] += 1
if a[i] > ma:
if lr[ma][1] != lr[ma][0]:
las = ma
else:
las = lr[ma][2]
lr[a[i]] = [i, i, las]
ma = a[i]
lr[ma][1] = i
res = sum(a)
for ma in range(1, n+1):
l, r, las = lr[ma]
if l == -1 or r == -1:
continue
elif l == r:
res += ma+las*(n-l-1)
# print(ma, las, (n-l-1), las*(n-l-1), ma+las*(n-l-1))
else:
res += cal(n-l, r-l+1)*ma
# print(ma, cal(n-l, r-l+1), cal(n-l, r-l+1)*ma)
# print(lr)
print(res)