CF刷题记录

数据结构(3):
1、1690G,我一开始想的是用set维护每一节火车的信息,然后用线段树修改和查询每一个数所在的火车段的值,然后写的有问题就写不下去了,其实只需要用set维护每一节火车的开头那个值的下标就行了,我们每次修改增加的火车段最多为1,而减少的段有多个,但开始火车段最多有n个,因此我们总的增加和减少的数量不会超过2n,因此可行。
2、1667B,我们考虑dp,令dp[i]为将前i个数划分所得的最大值,那么状态转移为dp[i]=max(dp[i], dp[j]+v(j+1,i)),j<i,v(j+1,i)为将这一段划分出来的价值,显然这样的转移是n的2次方的。这里有个结论,可以发现如果最优解中存在一段的总和为0或负数,那么这一段的长度一定为1,显然当我们存在一段和为负数时,我们将其分成两半,那么我们的值一定不会增加,那么如果和为0时,当长度为偶数时值一定不会增加,为奇数时,我们将其看作(k-1)/2, 1, (k-1)/2的形式,前一段的值为负数或后一段的值为负数时价值增大,而不满足这个条件时,价值一定不会减小。因此对于存在总和为负数时我们总可以在dp[i]=max(dp[i],dp[i-1]+v(i))取得,那么我们考虑总和为正数的情况,可以发现此时状态转移方程可以表示为dp[i]=max(dp[i],dp[j]+i-j),j<i,因此就dp[j]-j我们可以取总的最值来获得,而j的位置我们可以通过前缀和的值获得,显然这里不能通过简单的线性枚举获得,我们可以用树状数组或线段树得到,即满足s[j]<s[i]的位置的dp[j]-j的最大值这样的数据。其实我对树状数组的应用一直局限于二维偏序的问题的解决,并且是在树状数组的下标容易得到的题目,其实这题后面的条件也算看作二维偏序,只不过这里下标位置我们需要同排序二分得到,就是多加了这一步我就不知道怎么做了。
3、1566D2,显然二维偏序问题,用树状数组解决,但是当数的a[i]值相同时我们需要贪心考虑,显然我们选择位置小的放后边,这里存在一些问题,当值相同的点横跨多排时,我们需要选择更小的放前面,更大的放后边,我们双指针找出,然后对于reverse一下就行了。
4、1548B,对于ai到aj对m取模相同,我们可以发现他们相邻的两个数的差的绝对值为某个数m的倍数,也就是说我们取相邻的两个数的差的绝对值取gcd,那么这个gcd的值即为m,因此问题就转化成求i开始取差的gcd大于1的最大长度,这个问题很典型,就是用st表加二分求。
5、1547F,这题跟上题一样,用st表求gcd的值,但是我们这里题目所求不是取gcd大于1的最大长度了,而是二分最小操作次数,然后判断n个数是否相等,因为存在头尾相接,因此我们可以取长度的两倍,记得数组大小也取成两倍,这里没取tle了一发。
6、1526C2,如果当前选择的数使得我们的生命值小于0,那么我们必然需要删去一些数,显然我们选择删去最小的数,这样是可行的,因此我们用一个优先队列,每次插入元素并判断需不需要删去元素,那么最终的队列大小即为答案。
7、1499C,向右需要走n步,向上需要走n步,我们发现光贪心思考很难想明白,但是我们可以发现如果我们走的线段总数为i时,我们最优的选择是确定的,即取向上的为偶数线段,向右为奇数线段,那么我们一定是取其中最小的值多走,其他则走1步,因此我们枚举走了i条线段,并处理出前缀最值求解。
8、1498C,这是一道dp题(明明搜的tag是数据结构),可以发现如果我们对n,k的一些情况进行模拟计算会存在很多情况,因此我们就可以通过动态规划将这样的情况转化为一个一个的状态,因此我们取dp[pos][age][dir]表示位置在pos块板上生命为age,方向为dir的数量。那么状态转移方程则为dp[pos][age][dir]+=dp[pos-1][age-1][1-dir]+dp[pos+1][age][dir],根据方向的不同需要进行一些修改,初始化则为dp[pos][1][0/1]=1。但是这里存在一些问题,我们这样初始化以及表示的状态,对于第1块和第n块存在原子飞向外边从而缺少计数,也就是说我们转移方程中考虑了向左和向右,但是我本身飞出的这两个原子我们没有计数,而是记录在了左边和右边的dp值里,但是我们飞向外边时没有dp值,因此我们需要加上,而且不是加在某个dp值里,因此我们用记忆化搜索的方式dp更好。
9、1497E1,如果两个数的乘积为某个数的平方的话,那么他们的乘积的质因子的数量都为偶数,因此我们将每个ai进行质因数分解,将其每个质因子的数量对2取余,这样得到一个新的数列,那么我们的问题就转化成了在这个数列上求连续的段中不存在相等的数的最小线段数,显然我们用双指针就可以解决。
10、1492C,首先贪心的想情况很多,因此我们思考枚举在i这个位置取得最大值的值为多少,我们取从前往后取pre[i]使t的前i个字母匹配的最小位置,从后往前取suf[i]使t的后面所有字母匹配的最大位置,取所有pre[i]和suf[i+1]的差的绝对值的最大值即为答案。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wlzsgl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值