【test】2024.10.8

次大值

思路

发现性质,对于一个数

\[a[i]\%a[j]\le a[i] \]

当他取得最大值时\(a[i]<a[j]\)
于是对于前&n-1&大的数,他的贡献值就是他本身,所以我们只需要保存第\(n-1\),\(n-2\)大的数就可以。
但是此时要注意第\(n\)大的数的贡献值没有计算,由于\(a[n]\%a[n-2]<a[n-2]\),所以如果他要对答案有贡献,当且仅当

\[a[n]\%a[n-1]>a[n-2] \]

因此我们只需要保存前\(3\)大的数即可。
注意,如果去重后只有\(2\)个数,那么答案就是\(a[2]\%a[1]\)。如果只有\(1\)个数,那么输出\(-1\)

\(code\)

我还没写正解。QAQ

倒水

思路

如果一堆瓶子最后可以合为一个,那么这堆瓶子的个数就一定是\(2^i\)
根据谈心原则如果想让当前瓶子数减少\(1\),那么只需要加上瓶子数的\(lowbit\)。即

\[x\&(-x) \]

注意,每次操作完后总瓶子数不一定减1。

\(code\)

code

Count Interval

思路

我们设\(s[i]\)表示右端点为\(i\)的前缀和,于是满足条件的区间\([l,r]\)\(s[r]-s[l-1]=k\)
移项就可以得到

\[s[r]=s[l-1]+k \]

得到正解。我们从\(1\)\(n\)遍历序列,遍历同时,开一个桶,记录\(s[i]+k\)的个数。
注意,要开\(map\)

\(code\)

我也没写,QWQ

飞行路线

\(solution 1\)

就是分层图的板子,时间复杂度\(O(k*nlog_2(k*n))\)

\(solution 2\)

利用\(DP\)思想,设\(f[i][j]\)表示到第\(i\)个点,已经使用\(j\)此免费机会时的最小花费。

\[f[i][j]=min(f[i][j],f[k][j]+w,f[k][j-1]) \]

利用这个转移方程,再跑一遍\(dijkstra\)
!!!注意 1.\(vis\)数组要开二位,即把每一个\(pair(i,j)\)看成一个独立的点
2.跑\(spfa\)会被卡

\(code\)

code

262144 P

思路

一道非常好的\(DP\)题目,暴力就是区间DP,设\(f[i][j]\)表示区间\(i,j\)中所能合成的最大数的值。
但是由于\(i,j\)都很大,所以状态错误,此时联想到一道\(ATcoder\)\(DP\)题目,考虑是否能互换状态,然后这道题就做完了。
\(f[i][j]\),表示左端点为\(i\),合成出\(j\)的区间右端点。由于\(j\le 40*+log_2n\)所以状态正确。
当左端点确定,且合成出数确定后,由于序列是给定的,右端点显然也是确定的。利用倍增思想

\[f[i][j]=f[f[i][j-1]+1][j-1] \]

最后的答案就是\(f\)值不为0的最大\(j\)
注意,决策时要保证\(f[i][j-1]\)不为0,因为如果为0就表示一个\(i-1\)无法合成

\(code\)

code

Yet Another Monster Killing Problem

思路

考虑贪心,对于每一个\(i\),都想让它扩展出去最远,由于当前决策不会影响以后和以前的决策,所以贪心具有正确性。
对于一个区间,他是否能在一天内被打完,取决于,是否有一个英雄,他的耐力值大于等于该区间,且他的战斗力大于等于区间怪物战力最大值。
对于耐力值相同的英雄,显然我们要保留战力最大的那一个。
此时我们可以设两个桶\(f[i],s[i]\),分别表示耐力值为\(i\)的实力最大值,和耐力值大于等于\(i\)的最大实力。
其中

\[s[i]=max(s[i+1],f[i]) \]

由于\(s[i]\)\(i\)减小而增加,区间最大值随区间长度增加而增加,都满足单调性,所以可以写一个类似双指针的东西

\(code\)

我写的代码丢了,至今未调出来,QWQ

青蛙过河

思路

这题显然可以二分跳跃能力,那么问题是如何写\(check()\)
先看性质,如何由任何一个长度为\(d\)(跳跃能力)的区间中\(h[i]\)的和小于\(2*x\),那么就不合法。
先证明必要性
对于一个区间和小于\(2*x\),那么一定会出现一种情况,使青蛙在区间左端点时无法跨越这一个区间。
再证明充分性
既然每一个区间都满足,那么青蛙一定可以在任意时刻的任一点,找到一个落地点。

\(code\)

code

Zuma

思路

有一个很重要的性质,对于每一个区间,他一定可以被分为若干个回文串(单个字符也算是回味串)。
这题一眼区间\(DP\),设\(f[i][j]\)表示合并完\([i,j]\)所用的最小时间。

\[f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]) \]

注意\(k<j\)
特殊的如果\(a[i]=a[j]\),那么之间的字符串,由性质可以得到,一定可以被合并位一个回文串,此时合并不需要额外花费

\[f[i][j]=min(f[i+1][j-1],f[i][j]) \]

注意需要特判如果\(i-j+1=2\),那么中间为空,此时\(f[i][j]=1\)

\(code\)

代码丢了,崩

posted @ 2024-10-09 16:31  GuoSN0410  阅读(15)  评论(0)    收藏  举报