思路:
先将时间进行离散化,设总时间为 \(cnt\),然后考虑求出 \(W(l,r)\),即在时间段 \([l,r]\) 内的所有节目,可以 \(n^2\) 前缀和,也可以 \(n^3\) 暴力。
然后定义 \(f_{i,j}\) 表现前 \(i\) 个时间,一号园地有 \(j\) 个节目时,二号园地最多的节目数量,则状态转移方程为:
\[f_{i,j} = \max\limits_{k=0}^{i-1} \max(f_{k,j} + W(k,i),f_{k,j-W(k,i)})\]
那么可以得到:
\[ans_0 = \max\limits_{i=0}^n \min(i,f_{cnt,i})\]
则第一个问的时间复杂度为 \(O(N^3)\)。
然后再看第二个问,需要定义 \(g_{i,j}\) 表现 \(i \sim cnt\) 的时间段,一号园地有 \(j\) 个节目时,二号园地最多的节目数量,则状态转移方程类似:
\[g_{i,j} = \max\limits_{k=i+1}^{cnt} \max(g_{k,j} + W(i,k),g_{k,j-W(i,k)})\]
然后再定义 \(dp_{l,r}\) 表现若强制选 \([l,r]\) 的全部节目的局部最优解,则可以摆列左边和右边一号场有多少个进行转移:
\[dp_{l,r} = \max\limits_{i=0}^n \max\limits_{j=0}^n \min(i+W(l,r)+j,f_{l,i} + g_{r,j})\]
那么此时若强制选 \([l,r]\) 的答案,是 \(dp_{l,r}\) 吗?答案很明显,不是。
因为 \(f_{l-1,i}\) 和 \(g_{r+1,j}\) 只保证了 \(1 \sim l-1,r+1 \sim j\) 的局部最优,即可能会有一些活动的一端在 \([l,r]\) 内,但是另一端不在 \([l,r]\) 内,此时选这些节目可能会更优。
于是我们需要摆列一个 \([L,R]\),使得 \([L,R]\) 包罗 \([l,r]\),故 \([l,r]\) 强制选的答案为:
\[\max_{L=1}^l \max_{R=r}^{cnt} dp_{L,R}\]
故只要我们求出 \(dp\),就可以 \(O(N^3)\) 的得到答案。
但是盘算 \(dp\) 的时间复杂度为 \(O(N^4)\),且常数较大,需要优化卡常大家应该能冲过去。
注意到 \(f_{l,i}\) 和 \(g_{r,j}\) 是会随着 \(i/j\) 的增大而不增的。
此时若 \(i\) 不动,则对于 \(j\) 来说, \(i+W(l,r)+j\) 是单增的,\(f_{l,i} + g_{r,j}\) 是单降的,故 \(H(y)=\min(i+W(l,r)+j,f_{l,i} + g_{r,j})\) 是一个单峰的函数,我们需要找到其最大值。
故我们可以对 \(j\) 进行走指针,从 \(yjn\) 开始,若 \(H(j-1)\ge H(j)\),就可以令 \(j \gets j - 1\)。
这里需要证明一下在 \(i\) 增加时,\(j\) 的单峰函数只会向左平移,因为这样才可以走指针:
在 \(i\) 增加时,\(i+W(l,r)+j\) 也会增加。
而对于 \(f_{l,i}+g_{r,j}\) 不增。
故会峰点左移。
总时间复杂度是 \(O(N^3)\)。
完整代码:
[code]#include#define Add(x,y) (x+y>=mod)?(x+y-mod) x+y)#define lowbit(x) x&(-x)#define pi pair#define pii pair#define iip pair#define ppii pair#define fi first#define se second#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x#define Full(a) memset(a,0,sizeof(a))#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);using namespace std;typedef double db;typedef unsigned long long ull;typedef long long ll;bool Begin;const int N=205,M=410,INF=1e9; inline ll read(){ ll x=0,f=1; char c=getchar(); while(c'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c |