思路是很简单的,就是以时间为主线,在当前时刻,先统计出所有该时刻提出的idea
然后以PM为类别分组这些idea即代码中的group
然后计算出每个PM最想先实现的idea,记录在IdeaPriority中
然后就是遍历每个程序员,只要程序员在该时刻空闲,就从IdeaPriority中按题目要求选出一个idea给其完成
遍历完每个程序员后也就是说在当前时刻遍历完了所有程序员,然后时刻+1,
继续循环,即统计出所有这新时刻下提出的idea,,,,,,,,,,
下面是python 版本,由于耗时只通过了60%,所以还是用C快一下,有时间再写一个c版本的吧!!!
N,M,P = [int(e) for e in input().split()]
idea = []
for i in range(P):
idea.append([int(e) for e in input().split()]+[i])
idea.sort(key = lambda x:x[1])
finsh = 0 #程序员完成的idea个数
NoTime = 1 #当前时刻
last = 0 #上一次idea进入的下标
Program = [0 for _ in range(M)] #程序员直到空闲的时刻
NoTimeIdea = [] #当前时刻待解决的idea
result = {} #结果
group = {} #当前时刻各个程序员提出的idea集合
while finsh<P:
#当前时刻待解决的所有idea
for i in range(last,P):
if idea[i][1]==NoTime:
if idea[i][0] not in group:
group[idea[i][0]] = [idea[i]]
else:
group[idea[i][0]].append(idea[i])
if i==P-1:
last = P
else:
last = i
break
#选出每个产品经理最想实现的idea
IdeaPriority = []
for j in group.keys():
group[j].sort(key = lambda x:(-x[2],x[3],x[1]))
IdeaPriority.append(group[j][0])
#给每个程序员选出需要解决的idea
for i in range(M):
IdeaPriority.sort(key = lambda x:(x[3],x[0]))
if Program[i]<=NoTime and len(IdeaPriority)!=0:
Program[i] = NoTime+IdeaPriority[0][3]
result[IdeaPriority[0][4]] = Program[i]
j = IdeaPriority[0][0]
index = IdeaPriority[0][4]
#从IdeaPriority中删除已经解决的idea
IdeaPriority.pop(0)
#从group中删除已经解决的idea
for p in range(len(group[j])):
if group[j][p][4]==index:
group[j].pop(p)
if len(group[j])==0:
del group[j]
else:
group[j].sort(key = lambda x:(-x[2],x[3],x[1]))
IdeaPriority.append(group[j][0])
break
finsh+=1
NoTime+=1
for i in range(P):
print(result[i])
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
此题的关键是要读出如下信息:
因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间
即我们可以先给整个查询按照第一个字段排序(即待查询用户的起始标号),这里采用升序
排序后注意:
只会出现如下区间错位:
即类如[2,6] [4,8]
而不会出现:
所以经过排序后,假设当前这一组的查询区间为 [L_now, R_now],紧挨着其下一组是[L_next, R_next]
那么一定是:
L_now<L_next<=R_now
R_now<R_next
好了,下面我们进入正题:
首先我们使用一个字典来记录当前待查询区间下每一个喜好值对应的人数
-------------------------------------------------------------------------------------------------------------------------------------
举例:有一组喜好值
1,4,3,5,5,7,3,5,9,10
可以看到喜好值有1,3,4,5,6,7,9,10这几种:
假设当前查询的区间是[2,6]即4,3,5,5,7那么字典中记录的应该是:
1:0
3:1
4:1
5:2
6:0
7:1
9:0
10 : 0
那么我们再看一下当前待查询区间要查询的喜好值,比如说是5,那我们从字典中找到对应的key下的value即可这里是2
---------------------------------------------------------------------------------------------------------------------------------------
所以我们就将待查询的数据一组组输入,然后统计该区间内的各个喜好值,最后对应查询即可
问题转化为怎么统计该区间内的各个喜好值,本题的巧妙之处就在于这里的动态规划:
假设现在我们统计的是下一组(图中下面一个条形框)
由于我们上一组已经统计过了(图中上面一个条形框),可以看到其实黄色部分是可以利用的,不用在重新统计,换句话说:
丢弃蓝色,保留黄色,再多统计一下灰色
这里采用的方法是:
遍历蓝色中的每一个元素,在字典中使该元素减一
遍历灰色中的每一个元素,在字典中使该元素加一
可以想象结果就是:
丢弃蓝色,保留黄色,多统计了一下灰色
代码如下:
_ = input()
arr = []
d = {}
for e in input().split():
arr.append(int(e))
d[int(e)] = 0
n = int(input())
temp = []
for i in range(n):
e = input().split()
e[0] = int(e[0])-1
e[1] = int(e[1])-1
e[2] = int(e[2])
temp.append(e+[i])
temp.sort()
result = []
left = 0
right = -1
arr[0] = 1
for i in range(n):
tempList = temp[i]
left_interval = tempList[0] - left
right_interval = tempList[1] - right
for l in range(left_interval):
d[arr[left+l]]-=1
for r in range(right_interval):
d[arr[right+r+1]]+=1
if tempList[2] in d:
result.append([d[tempList[2]],tempList[3]])
else:
result.append([0,tempList[3]])
left = tempList[0]
right = tempList[1]
result = sorted(result,key = lambda x:x[1])
for i in range(n):
print(result[i][0])
代码中的d就是字典
for l in range(left_interval):
d[arr[left+l]]-=1
就是天蓝色
for r in range(right_interval):
d[arr[right+r+1]]+=1
就是灰色
if tempList[2] in d:
result.append([d[tempList[2]],tempList[3]])
else:
result.append([0,tempList[3]])
就是记录一下当前这一组的查询结果
这里的tempList[3]只是为了便于结果按顺序输出,因为开头排了一下序,所以顺序是乱的,所以多加了一个索引即:
temp.append(e+[i])中的[i]