CF1442D Sum
脑子真的不够用。。。
如果想到凸包差不多就是掉坑里了
注意到这个玩意的前缀和确实是凸的
然后发现一个性质就是在选的数组里,最多只有一个数组不会被全选
全选的部分可以 \(O(nk)\)
于是可以考虑分治,用左边的暴力转移右边全选的,右边的暴力转移左边全选的
复杂度 \(O(nklogn)\)
#include <bits/stdc++.h>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
const int N=3005;
typedef long long ll;
typedef double db;
# define chkmax(a,b) a=max(a,b)
# define chkmin(a,b) a=min(a,b)
# define PII pair<int,int>
# define mkp make_pair
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m;
ll f[N<<2][N],g[N];
vector<ll> s[N];
int a[N];
void solve(int u,int l,int r){
if(l==r){
Rep(i,0,min(a[l],m))f[u][i]=s[l][i];
return;
}
int mid=l+r>>1;
int lc=u<<1,rc=u<<1|1;
solve(lc,l,mid),solve(rc,mid+1,r);
Rep(i,l,mid)_Rep(j,m,a[i])chkmax(f[rc][j],f[rc][j-a[i]]+s[i][a[i]]);
Rep(i,mid+1,r)_Rep(j,m,a[i])chkmax(f[lc][j],f[lc][j-a[i]]+s[i][a[i]]);
Rep(i,0,m)f[u][i]=max(f[lc][i],f[rc][i]);
}
int main()
{
// freopen("testdata.in","r",stdin);
read(n),read(m);
Rep(i,1,n){
read(a[i]);
s[i].resize(a[i]+2);
Rep(j,1,a[i])read(s[i][j]);
s[i][0]=0;
Rep(j,1,a[i])s[i][j]+=s[i][j-1];
}
// Rep(i,1,n)Rep(j,1,a[i])printf("%lld%c",s[i][j],j==a[i]?'\n':' ');
solve(1,1,n);
printf("%lld\n",f[1][m]);
return 0;
}