第一行输入一个整数
代表同学数量。
第二行输入
个整数
代表每一位同学的身高。
输出一个整数,代表最少需要出列的同学数量。
8 186 186 150 200 160 130 197 200
4
在这个样例中,有且仅有两种出列方式,剩下的同学分别为
和
。
import bisect def max_l(l, dp): b = [float("inf")] * len(l) # 初始化递增序列 for i in range(len(l)): pos = bisect.bisect_left(b, l[i]) # 找到插入位置 b[pos] = l[i] # 更新递增序列 dp[i] = pos + 1 # 更新 dp return dp def max_r(l, dp): b = [float("inf")] * len(l) # 初始化递增序列(倒序处理递减序列) for i in range(len(l) - 1, -1, -1): pos = bisect.bisect_left(b, l[i]) # 找到插入位置 b[pos] = l[i] # 更新递增序列 dp[i] = pos + 1 # 更新 dp return dp # 主程序 while True: try: n = int(input()) l = list(map(int, input().split())) # 边界条件处理 if n == 1: print(0) continue left = [0] * n right = [0] * n left = max_l(l, left) right = max_r(l, right) max_val = 0 for i in range(n): max_val = max(max_val, left[i] + right[i] - 1) print(n - max_val) # 输出最少需要移除的人数 except EOFError: break
import bisect def inc_max(s): q = [] dp=[] for n in s: idx = bisect.bisect_left(q, n) dp.append(idx+1) if idx == len(q): q.append(n) else: q[idx] = n return dp N = int(input()) s = list(map(int, input().split())) left_s = inc_max(s) # 从左至右 right_s = inc_max(s[::-1])[::-1] # 从右至左 sum_s = [left_s[i] + right_s[i] - 1 for i in range(len(s))] # 相加并减去重复计算 print(str(N - max(sum_s))) #总感觉题解中使用二分法很勉强,看的迷迷糊糊的,感觉这样写会比较明白一些
n = int(input()) list1 = list(map(int, input().split())) def LengthOfLis(lt): # 定义函数找出最长递增子序列长度 if not lt: return 1 lt2 = lt[::-1] # 反向找最长递增子序列 dp = [1 for _ in range(len(lt))] dp2 = [1 for _ in range(len(lt))] for i in range(1, len(lt)): # 找左边最长 for j in range(i): if lt[j] < lt[i]: dp[i] = max(dp[i], dp[j] + 1) for i in range(1, len(lt2)): # 找右边最长 for j in range(i): if lt2[j] < lt2[i]: dp2[i] = max(dp2[i], dp2[j] + 1) dp3 = list(map(lambda x, y: x + y, dp2[::-1], dp)) # 左边加右边 为总长度+重复一项 return dp3 print(n - max(LengthOfLis(list1)) + 1) # 原长度-(最长+1),再+1为减去的长度
# 关键点,不再使用遍历找最大值的方法,直接使用二分法维护一个排好序的数组 # 时间复杂度为O(nlog(n)) import bisect n = int(input()) nums = list(map(int, input().split())) def dpHelper(nums): n = len(nums) arr = [nums[0]] dp = [1]*n for i in range(1,n): if nums[i] > arr[-1]: arr.append(nums[i]) dp[i] = len(arr) else: # 此处使用二分查找,将该nums[i]插入到序列中,同时dp[i]为插入的位置+1 # 为什么不用insort,因为arr更像是正常查询时得到数组的叠加状态,仅服务于后面的查询 index = bisect.bisect_left(arr, nums[i]) arr[index] = nums[i] dp[i] = index + 1 return dp dpleft = dpHelper(nums) dpright = dpHelper(nums[::-1])[::-1] res = 0 for i in range(n): tres = dpleft[i] + dpright[i] - 1 if res < tres: res = tres print(n - res)
# def solution(nums): #基础动态规划,O(n*n) 超时 # n = len(nums) # if n <= 2: return 0 # dp = [[1,1] for _ in range(n)] #0 上升,1 下降 # maxL = 1 # for i in range(1,n): # for j in range(i-1,-1,-1): # if nums[i] > nums[j]: # dp[i][0] = max(dp[i][0],dp[j][0]+1) # elif nums[i] < nums[j]: # dp[i][1] = max(dp[i][1],dp[j][1]+1,dp[j][0]+1) # maxL = max(maxL,dp[i][0],dp[i][1]) # return n-maxL import bisect #利用二分查找优化,dp含义改变为递增子序列 def ascMax(nums,dp): #O(nlogn) dp += [1] b = [float('inf') for _ in range(len(nums))] #b[i]代表当前长度为i+1的递增子序列中,结尾值最小为b[i] b[0] = nums[0] for i in range(1,len(nums)): pos = bisect.bisect_left(b,nums[i]) #找到使b保持严格升序的插入点 b[pos] = nums[i] #插入 dp += [pos+1] #记录以num[i]结尾的最长递增子序列 while True: try: n = int(input()) nums = list(map(int,input().split())) dp1,dp2 = [], [] ascMax(nums,dp1) #获得最长递增子序列 ascMax(nums[::-1],dp2) ##获得最长递减子序列 dp2 = dp2[::-1] maxVal = 1 for i in range(n): maxVal = max(maxVal,dp1[i]+dp2[i]-1) #以nums[i]为最大值的合唱队长度 print(n - maxVal) except: break
n = int(input()) seq = list(map(int,input().split())) def lis(sequence): dp, sort = [1], [] for s in sequence: if not sort: sort.append(s) else: if sort[-1] < s: sort.append(s) dp.append(len(sort)) continue i, j = 0, len(sort) - 1 #二分搜索 sort 中第一个大于等于s的数字并替换 while i <= j : n = (i + j) // 2 if sort[n] < s: i = n + 1 elif sort[n] > s: j = n - 1 else: i = n break sort[i] = s # i + 1 即为 以s结尾的最长递增子序列的长度 dp.append(i+1) return dp # 正反各一遍 inc = lis(seq) deq = lis(seq[::-1])[::-1] # 去掉首位,因为序列中最大数的左右两边都要有递减序列,不能为空 print(n - max([inc[i]+deq[i]-1 for i in range(1,n-1)]))Longest Increasing Subsequence(最长递增子序列)的O(nlogn)解法
s_len = int(input()) s_arr = [int(i) for i in input().strip().split(' ')] left_up = [] right_down = [] def countleftup(arr:list): longest = 0 dp = [1 for i in range(len(arr))] for i,v1 in enumerate(arr, 0): for j,v2 in enumerate(arr[:i], 0): if v1 > v2:# can up dp[i] = max(dp[i], dp[j] + 1) longest = max(longest, dp[i]) return dp def countrightdown(arr:list): longest = 0 dp = [1 for i in range(len(arr))] temp_index = [i for i in range(len(arr))] temp_index.reverse() for i in temp_index:# 一级索引为i for j,v in enumerate(arr[i + 1:], 0): # 二级索引为i + j,部分为:【i + 1:】 if v < arr[i]:# 如果一级值大于二级值 dp[i] = max(dp[i], dp[i + j + 1] + 1) longest = max(dp[i], longest) return dp min_out = len(s_arr) - 1 left_up = countleftup(s_arr) right_down = countrightdown(s_arr) for i,v in enumerate(s_arr, 0): left_max = 0 right_max = 0 for j,v_left in enumerate(left_up[:i]): if s_arr[j] < v: left_max = max(left_max, v_left) for j,v_right in enumerate(right_down[i + 1:]): if s_arr[j] < v: right_max = max(right_max, v_right) out = len(s_arr) - left_max - right_max - 1 min_out = min(min_out, out) # print(left_up) # print(right_down) print(min_out)
def left_max(l): # 使用自己的长度1初始化dp数组 # dp表示第i个人前面最大升序列的长度 dp = [1] * len(l) for i in range(len(l)): # 遍历队列中的每一个人 for j in range(i): # 遍历当前人前面的每一个人 # 如果当前人前面的人比当前人高,并且当前人前面的最大升序列长度 if l[j]<l[i] and dp[j]+1>dp[i]: dp[i]+=1 return dp while True: try: N = int(input()) ss = list(map(int, input().split())) left_ss = left_max(ss) right_ss = left_max(ss[::-1])[::-1] sum_s = [] for i in range(len(left_ss)): sum_s.append(left_ss[i]+right_ss[i]-1) print(str(N-max(sum_s))) except: break 大神“MIN大小姐”的题解非常有效。我来讲讲我对状态转移方程的认识。dp[i]状态数组表示在第i个人及其前面、满足升序列的最大长度。dp数组用1初始化,表示当前只考虑自己。状态转移方程if l[j]<l[i]表示前面的人比自己矮,dp[j]+1>dp[i]表示在当前人前面有和自己前面相同数量的最大升序列。因此if l[j]<l[i] and dp[j]+1>dp[i]表示当前人比之前的人高,并且当前人的前面的人有和当前人前面一样长度的上升序列。所以当前人的状态变为dp[i]+1
不知道 提交的时候为什么错,自测都对的。 n = int(input()) lst = [] while True: try: lst = list(map(int,input().split())) inc = [] for i in range(len(lst)): tmp = [] tmp.append(lst[i]) flag = 0 for j in range(i+1,len(lst)): if lst[j] > tmp[-1]: tmp.append(lst[j]) flag = j if flag != 0: for j in range(flag,len(lst)): if lst[j] < tmp[-1]: tmp.append(lst[j]) inc.append(tmp) inc.sort(key=len) print(len(inc[-1])) except:
# 动态规划
def lengthOfLIS(lst):
dp = []
for i in range(len(lst)):
dp.append(1)
for j in range(i):
if lst[i] > lst[j]:
dp[i] = max(dp[i], dp[j] + 1)
return dp # 每人左边可以站的人数
while True:
try:
n, heights = int(input()), list(map(int, input().split()))
# dp1:每人左边可以站的人数,dp2:每人右边可以站的人数
dp1, dp2 = lengthOfLIS(heights), lengthOfLIS(heights[::-1])[::-1]
res = []
for i in range(len(dp1)):
res.append(dp1[i] + dp2[i] - 1)
print(n-max(res))
except:
break
#最烦的莫过是代码写对了,自测运行都通过了,提交时没有输出,还不告诉你原因,不知道是什么原因,希望有哪位大佬给我看下 def dfx(b): c =[] d =[] for i, _ in enumerate(b): if c == []: c.append(_) d.append(len(c)) else: if _ > max(c): # print(_) c.append(_) d.append(len(c)) else: for j, __ in enumerate(c): if _ <=__ : c[j] = _ d.append(len(c)) break return (c,d) while True: try: a = input() b = list(map(int,input().split(" "))) except Exception as e: # print(e) break else: c1 = dfx(b) b.reverse() c2 = dfx(b) c2[1].reverse() for i, _ in enumerate(c1[1]): c1[1][i] = _ + c2[1][i] print(int(a)-max(c1[1]) +1)