题目简介
正在 rainbow 的城堡游玩的 Freda 恰好看见了在地毯上跳舞卖萌的水叮当……于是……
Freda:“呜咕>_< 我也要卖萌T_T!”
rainbow 给了 Freda \(N\) 秒的自由活动时间,不过由于刚刚游览城堡有些累了,Freda 只想花 \(B\) 秒的时间来卖萌,剩下的时间她要在 rainbow 的城堡里睡个好觉好好休息一下。
rainbow 给这 \(N\) 秒每秒定义了一个值 \(U_i\),如果第 \(i\) 秒钟 Freda 在卖萌,那么她可以获得 \(U_i\) 点卖萌指数lala~
Freda 开始卖萌后可以随时停止,休息一会儿之后再开始。不过每次 Freda 开始卖萌时,都需要 \(1\) 秒来准备= =,这一秒是不能获得卖萌指数的。当然,Freda 卖萌和准备的总时间 不能超过 \(B\)。
更特殊的是,这 \(N\) 秒钟时间是 环形 的。也就是 Freda 可以从任意时间开始她的自由活动并持续 \(N\) 秒。
为了使自己表现得比水叮当更萌,现在 Freda 想知道,她最多能获得多少卖萌指数呢?
输入格式
第一行包含两个整数 \(N\) 和 \(B\)。
第 \(2\)~\(N+1\) 行每行一个整数,其中第 \(i+1\) 行的整数表示 \(U_i\)。
输出格式
输出一个整数,表示 Freda 可以获得的最大卖萌指数。
数据范围
各个测试点时间限制 \(1\mathrm{s}\),空间限制 \(1\mathrm{GiB}\)。
- 对于 \(60\%\) 的数据,\(N\leq 100\)
- 对于 \(100\%\) 的数据,\(0\leq B\leq N\leq 3600\),\(0\leq U_i\leq 200000\)。
分析
这道题可以看出来是 \(\mathtt{DP}\),只不过环形这个条件比较难搞。
线性情况
状态定义和递推
先考虑线性的情况,定义 \(f_{i,j}\) 为前 \(i\) 分钟已经卖萌 \(j\) 分钟的卖萌指数最大值。
则可以得到:(\(val(i,j)\)代表从 \(i\) 时刻到 \(j\) 时刻的卖萌指数)
\[ \huge{f_{i,j} = \max\{f_{i-1,j}, \max_{0< k\leq j}\{f_{i-k,j-k}+val(i-k+1,i)\}\}} \]
在这个基础上,我们发现这个算法的复杂度是 \(\Theta(n^3)\) 的,只能通过部分分。如何优化?
优化
首先,\(val(i,j)\) 是可以通过前缀和实现 \(\Theta(1)\) 的。接下来考虑 \(\max_{0< k\leq j}\{f_{i-k,j-k}\}\)
考虑数列 \(l_{k,u} = \max_{k\leq t\leq u}\{f_{t,t-k}\}\),则 \(\max_{0< k\leq j}\{f_{i-k,j-k}\}\) 就是 \(l_{i-j,i-1}\)。
每次计算出 \(f_{i,j}\) 后,可以 \(\Theta(1)\) 更新 \(l_{i-j,i}\),这样就可以将复杂度降至 \(\Theta(n^2)\)。
同时 \(l_{k,u}\) 可以简化成 \(l_k\),节省空间。(虽然这道题有的是空间)
上代码: