这道题刚开始以为挺简单的,直接暴力,每次选最大的,发现只能过极少的案例,后来想了很久,才想到用单调栈加二分,如果有大神知道更好的做法,恳请留言。
###########基础知识
1.单调栈
2.二分法
#################
对于直接暴力的解法其时间复杂度肯定是O(n*m)的,后来我想到用二分法对技能表进行从大到小的排序,每次选下标【0】的元素来用,用完后威力减去对应值(Ai-Bi),再用二分法插到相应位置,时间复杂度为O(m*logn),发现还是慢了!。
再后来我想到其实技能表在一开始排好序的时候 其要加那些威力就已经定了!!
#############解释
案例:n=3,m=6.arr=[[10,5],[9,2],[8,1]],
最终加威力顺序:【10,9,8,7,7,6】
####################
所以做了很多的无用二分操作,所以我建了一个大小为m的单调栈,对于单调栈的插入还是要用二分,具体如下
对于每一个输入的技能,其可提供的所有可能的种类有(Ai//Bi+1)个,我会将这所有的种类全部插入单调栈,(##如【10,3】会提供 【10】,【7】,【4】,【1】) 。细节:如果一个技能提供的第一个种类被插在了z位置,那么后面的种类将会在z~l而不是0~l
##############解释
案例:n=3,m=6.arr=[[10,5],[9,2],[8,1]], d(单调栈):[]
1,目前已输入【10,5】,生成种类【10】【5】【0】 d=[10,5,0]
2,目前已输入【9,2】,生成种类【9】【7】【5】【3】【2】【0】 d=[10,9,7,5,5,3]
3,目前已输入【8,1】,生成种类【8】【7】【6】【5】【4】..... d=[10,9,8,7,7,6]
最终结果为sum(d)=47
#############
代码如下:
#############################函数部分
def Binary_insert(a,loca):#二分插入,(新元素,loca>-1就不从0开头)
global arr,sum,m
l=len(arr)
q=loca if loca>-1 else 0
p=l-1
while q<=p:
mi=(q+p)//2
if arr[mi]>a:#缩头
q=mi+1
else:#缩尾
p=mi-1
arr.insert(q,a)
sum+=arr[q]
if len(arr)>m:
sum -= arr[m]
del arr[m]
return q
def Extract(a):#榨取所有种类
loca=-1
while a[0]>0:
loca=Binary_insert(a[0],loca)
a[0]-=a[1]
# ###########################输入部分
n,m=map(int,input().split())
sum=0#最终值
arr=[]#单调栈
for i in range(n):
a,b=map(int,input().split())
Extract([a,b])
# ##############################输出部分
print(sum)