1749C. Number Game
binary search/data structure/games/greedy/implementation, 1400, https://codeforces.com/problemset/problem/1749/C
Alice and Bob are playing a game. They have an array of positive integers 𝑎 of size 𝑛.
Before starting the game, Alice chooses an integer 𝑘≥0. The game lasts for 𝑘 stages, the stages are numbered from 1 to 𝑘. During the 𝑖-th stage, Alice must remove an element from the array that is less than or equal to
Your task is to determine the maximum value of 𝑘 such that Alice can win if both players play optimally. Bob plays against Alice, so he tries to make her lose the game, if it's possible.
Input
The first line contains a single integer 𝑡 (1≤𝑡≤100) — the number of test cases.
The first line of each test case contains a single integer 𝑛 (1≤𝑛≤100) — the size of the array 𝑎.
The second line contains 𝑛n integers
Output
For each test case, print one integer — the maximum value of 𝑘k such that Alice can win if both players play optimally.
Example
input
4
3
1 1 2
4
4 4 4 4
1
1
5
1 3 2 1 1output
2
0
1
31749C - Nubmer Game Tutorial, https://codeforces.com/blog/entry/108269
Note that if Bob has increased some element, then Alice can't remove it on the next stages. Obviously, it is more profitable for Bob to "prohibit" the smallest element of the array. Using this fact, we can iterate over the value of 𝑘, and then simulate the game process. To simulate the game, we can maintain the set of elements that Alice can remove. On the 𝑖-th stage, Alice removes the maximum element 𝑥, such that
Thus, the complexity of the solution is
There is another possible solution: we can notice that, if Alice wins, Bob will "prohibit" the elements on positions 1,2,…,𝑘−1 of the sorted array. So, Alice has to delete the next 𝑘 elements. So, if the segment [𝑘…2𝑘−1] of the sorted array can be deleted by Alice during the game phases, she wins with this value of 𝑘.
为了采取最优策略,Bob尽量从小的数开始增加k-i+1,而增加后的数将无法在以后的步骤中被Alice选取,为在后续步骤中能够继续选取,Alice尽量取满足条件的最大数来移除。
#import sys
from bisect import bisect_right
#from collections import deque
def solve():
n = int(input())
a = list(map(int, input().split()))
res = 0
for k in range(1, n + 1):
s = sorted(a)
for i in range(1, k + 1):
idx = bisect_right(s, k - i + 1)
if idx == 0:
break
s.pop(idx - 1)
if s:
now = s.pop(0)
s.append(now + k - i + 1)
s.sort()
if len(s) + k == n:
res = k
print(res)
def main():
t = int(input())
for _ in range(t):
solve()
if __name__ == "__main__":
main()# 2022fall-cs101, 梁力潇
t=int(input())
for i in range(t):
n=int(input())
l=list(map(int,input().split()))
l.sort()
if l.count(1)==0:
print(0)
continue
c=min(l.count(1),(n+1)//2)
l.remove(1)
for j in range(1,c+1):
if l.count(1)==0:
print(j)
break
l.remove(1)
d=[y for y in l if y<=j+1]
if d==[]:
print(j)
break
else:
l.remove(max(d))#from collections import deque
#from bisect import bisect_left
for _ in range(int(input())):
n = int(input())
*nums, = map(int,input().split())
numse = sorted(nums)
flag = True
if 1 not in nums:
print(0)
continue
for k in range(n+1):
nums = numse.copy()
for i in range(1,k+1):
if len(nums):
d = k-i+1
j = 0
while j<len(nums) and nums[j]<= d:
j+=1
if nums[j-1]> d:
flag = False
break
else:
nums.pop(j-1)
if len(nums):
nums[0]+=d
nums.sort()
else:
break
if not flag:
break
print(k-1 if not flag else k)2022fall-cs101,杨昊昆。先考虑清楚最后一步必须取1,也就是 k<=1 的个数,这样就完成了第一次剪枝;其次,思考 Alice的策略是删掉最大的数,Bob 的策略是把 k-i+1 加到最小的数字上;然后再考虑“有效数字”的问题,例如第一步,如果数列中有若干个k,实际上最后也只能对一个 k 进行删除操作,因此 k 的有效数字就是 1。排除了无效数字的影响后,也就不难得出总有效数字>=2k-1 的条件了。
2022fall-cs101,陈思源。这个题目需要想到正确的贪法。注意这样的事情:最后一轮总是Alice 取走1 才能赢,所以Bob 的最优策略是破坏Alice 的1,而不是破坏Alice 即将拿走。
𝑘 至少对应 2𝑘-1 个数字,𝑘 步之后 Alice 要选择 𝑘-i+1 = 1,那么 n 个数中至少需要有 𝑘-1 个1。
def solve():
n = int(input())
a = sorted(map(int, input().split()))
ans = 0
for i in range(n):
l = 0; r = i
c = (i+2)//2
chk = 0
while l <= r:
if a[r] <= c-l:
r -= 1 ; l += 1
else:
chk = 1
break
if chk == 0: ans = c
print(ans)
if __name__ == "__main__":
#for i in range(inp()):
for i in range(int(input())):
solve()2022fall-cs101,朱信霖,物理学院
考虑用贪心算法,k从1逐渐增大。取出前k-1个1后,之后的k个数满足a[i]>i+1。当以上条件不满足时,计算结束。 运行时间:31ms。时当前CF上使用python3解题的最短耗时。
t = int(input())
for _ in range(t):
n = int(input())
lis = [int(x) for x in input().split()]
lis.sort()
num = lis.count(1)
s = min(num,n//2+n%2)
check = False
for k in range(1,s+1):
lists = lis[k-1:2*k-1]
for i in range(k):
if lists[i] > i+1:
check = True
break
if check:
s = k-1
break
print(s)2022fall-cs101,胡靖苑,生命科学学院
思路:这道题比想象中简单,找到两个人采取的策略,根据策略找到需要的条件就行了。
import bisect
output=[]
for _ in range(int(input())):
n=int(input())
a=sorted(list(map(int,input().split())))
k=a.count(1)
while k>0:
flag=1
p=k
while p>=1:
j=bisect.bisect(a,p)
if j<k+p-1:
flag=0
break
else:
p-=1
if flag==1:
output.append(str(k))
break
else:
k-=1
if k==0:
output.append(str(0))
print('\n'.join(output))2022fall-cs101,成凌宇,物理学院。
本来是打算期中考试之后再细想这个代码的思路,但是回寝室以后和同学讨论了一下,突然发现这个代码非常妙。下面给出我的看法,首先 Alice 一定从最大的开始去,Bob 一定是从最小的开始加,那么如果最后 Alice 赢,那么 Bob 一定取了前 k −1 个,所以要求
for _ in range(int(input())):
n = int(input())
a = sorted(list(map(int, input().split())))
for k in range(n, -1, -1):
if all(k - 1 + i < n and a[k - 1 + i] <= i + 1 for i in range(k)):
print(k)
break