C(数据结构:区间加减、查询最值线段树)
大致题意:一个人在一个城市旅游,旅程有其开始时间和结束时间,给定n个任务,每个任务有其开始时间和结束时间,任务完成后会有奖励p,每在该城市待一天,都会花费k,现求旅程的开始时间和结束时间,使完成任务的奖励之和-花费之和最大(若最大值小于0则输出0,否则输出达到最大值时的开始、结束时间、所完成的任务的编号)
题解:可以将所有任务抽象成小区间,小区间被完全包含时,对答案有贡献,求小区间贡献和-k*区间长度的最大值
区间问题+数据范围2e5,很明显是枚举区间的R,找到最佳的L,再根据此时区间值判断是否更新答案,而对每个R找L时,往往需要借助线段树等数据结构达到log(并且往往是边枚举R边更新L的值)
首先化简问题,固定L为1,则很明显能预处理出一个前缀和数组RR。
而当L不为1时,则要将1~L-1区间对答案的影响消去(一部分来自k、一部分来自左端点<=L-1,右端点<=R的小区间)。
故先将小区间按右端点从小到大重新排列,设所有任务的右端点最大值为MAX,则枚举R从1到MAX,当枚举到i时,将所有右端点<=i的任务的影响插入线段树,将k的影响插入线段树(k这部分在建立线段树时就可预处理好),然后在1~i区间内查询最小值,(RR[i]-最小值)则为区间的右端点固定为R时,所能取到的最大值。
升级版:若小区间的端点范围开到1e12,小区间个数仍是2e5,易知最佳区间的R一定是某个任务的右端点,L一定是某个任务的左端点,故我们可以先将小区间的左右端点坐标离散化成4e5的范围,再开个4e5的pos数组记录离散化后的坐标和离散化之前的坐标的对应关系以计算k的影响,其他均与上述做法一致。
1 |
|
场后反思:
- 场上看错了数据范围,以为要离散化,浪费的时间++
- 明明思路想好了,code的时候忘记考虑小区间的R的影响,导致最后没写出来
- 再考虑L的影响区间时过于混乱(一部分也是开了离散化的锅),浪费了太多时间在瞎改code上,在code前就应该明确细节
G(博弈论、尺取法)
大致题意:给出、…,、…
现规定第i轮给两位选手分别加上,,规定谁先达到k谁输,若一同达到k或n轮之后都没达到k,则平局,选手1可在每轮结束后选择是否按下reset,若按下,记按下之前选手1的值为x,选手2的值为y,则按下后选手1的值为max(0,x-y),选手2的值为max(0,y-x)
求选手1能否获胜,若不能,输出-1,若能,则求选手1最少需要按几次reset才能获胜,并求出按下reset的对应回合
题解:观察reset操作,可看出reset操作后双方分数差值不变,相当于双方都减去双方分数的最小值,而不考虑k的限制时,多次reset操作都可看作在最后按reset的位置按一次reset,故可枚举获胜的位置(由后文贪心思路可知,越靠前所需按reset次数越少),得出获胜的最靠前位置,和其对应的最后一次按reset的位置,再枚举前面的回合,只有在即将到达k时才按reset,即可贪心得出最少按reset的次数
1 |
|