赛前训练题目思路总结5.13


A.水题


B.题意:有N长的区域来玩塔防游戏,接下来放置m个防御塔,每个防御塔有一个攻击区间和攻击经过这一点时造成的伤害。 接下来q次询问,问在x位置放置一个血量为H的怪,能不能通过防守。(N,m的范围都是1e6, H 1e18)

当时队友做这道题,将问题抽象成了N个值的线段,m次区间更新,然后计算出每个点的权值,直接O(1)处理询问。然后暴力肯定是不可以的,不能直接处理累加。根据题意,应该是裸的区间更新区间查询和的线段树,用O(nlogn)复杂度。 然后由于当时没有带模板,线段树不熟练,就没有打。然后我想了一个办法就是把每个区间更新的两个区间断点拆分,然后将所有区间端点排序,然后用O(N+m)的复杂度处理一次更新所有累加。  这样题目是过了,但是下来以后发现其实是不用排序的, 可以直接开一个比较大的数组,然后将区间拆分放到里面,然后直接O(n)复杂度就可以。 

这个题是先更新所有区间,然后再去查询,如果是一边更新一边查询可能就只能线段树了。


C.题意:n个机器,m个任务,每个机器和每个任务都有一个时间和等级,当机器的时间大于等于任务的时间且等级也大于等于任务的等级,这个机器可以完成这个任务。 每个机器只能完成一个任务,每个任务只能被一个机器完成。每完成一个任务获得(500*t+2*lev)的钱。 (数据范围1e6,等级<100)

根据数据范围,当时想的就是排序然后二分,一层遍历一层二分可以o(nlogn)复杂度过,但是想法其实是错的,排序以后也不能保证是否能完成任务处于有序性。

正确的解法是贪心,一直没有这样去想。 首先对机器和任务按照先时间后等级从大到小排序。然后从任务开始,按时间查找能完成它的所有机器,然后讲这些机器的所有level存到一个数组中保存,代表每个能完成当前任务的对应level的机器个数。这样以来,如果当前任务能够被这些机器在时间上满足可以完成,那么后面所有任务都满足,然后对于当前任务,将满足情况的机器中取出一个等级也满足且最小的机器去完成。  这样一直对任务扫下去即可。这样以来就可以用O(100n)的复杂度去贪心。


F.题意:m张背面朝上的扑克,n次操作,每次能够选取xi张不同的扑克翻面,问所有操作以后有多少可能。 结果对1e9+7取模。(数据范围1e6)

当时一直去想dp或者其他的办法,原来就是一个数学思维的题目,不算难。

将正面朝上看做1, 反面向上看做0, 初始状态为全0, 易知,最后1的个数一定和操作的总数奇偶性是相同的。  然后只要求出1的最大个数和最小个数,就可以求出最后1的个数的所有可能。 在去求1的组合就可以了,将所有组合加起来就是最后结果。

然后考虑如何去求最大的1的个数和最小的1的个数,数据范围1e6,所以可以针对每一次操作去模拟,要想得到最大的1,所以有0就翻转0, 没有的话只能翻一次1,然后下次就又可以翻0了。这样就可以根据当前1的个数和操作xi的大小确定每一次操作得到最多多少个1, 一直到最后一次操作。  要求最少的1的个数是一样的道理。

然后对所有的结果求组合数, 组合数涉及到了除法模运算,所以对分母上的数字求一下逆元,mod是质数,直接用费马小定理就可以了。


H.题意:题意比较复杂,简单来说,就是找一组数(每个数字<1e5),对于每一个数,找到它之前的数中是它倍数的最大的数的下标,找到它之后的数中是它倍数的最小数字的下标。 如果没有,就返回它自己的下标。然后求每个数字的这个东西。(数据范围1e5)

由于数字大小不超过1e5,可以预处理获得所有数字的所有因子,放到一个vector数组存储。然后通过两次遍历,一次正向遍历找之前的数字,一次反向遍历找之后的数字。在正向遍历的时候,对于每一个数字,根据预处理,可以得到它是哪些数字的倍数,然后存储这些数字中的最大倍数的下标。 这样每次找到下一个数字的时候就可以直接获得它之前的倍数的最大的下标。  在反向遍历处理的时候是一样的,只不过维护一个最小值即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值