题意
你有
思路
题目要求的是一个最大值的最小值,容易想到二分答案。
简单的贪心很容易举出反例,可以考虑 DP 。我们先求出
回到题目,
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN=220000;
const int MAXV=1E9;
int n, m, c;
int a[MAXN], f[MAXN];
ll s[MAXN], sub[MAXN];
struct BIT
{
int d[MAXN];
inline int lb(int x) { return x&-x; }
inline void init()
{
for (int i=1; i<=n; i++) d[i]=0;
}
inline void update(int x, int k)
{
if (x==0) return ;
while (x<=n) d[x]=max(d[x], k), x+=lb(x);
}
inline int query(int x)
{
int res=0;
while (x>0) res=max(res, d[x]), x-=lb(x);
return res;
}
} bit;
inline int read()
{
int x=0, f=0; char ch=0;
while (!isdigit(ch)) f|=ch=='-', ch=getchar();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48), ch=getchar();
return f?-x:x;
}
inline void discretize()
{
sort(sub+1, sub+n+1);
c=unique(sub+1, sub+n+1)-sub-1;
}
inline int key(ll x)
{
return upper_bound(sub+1, sub+c+1, x)-sub-1;
}
bool check(ll k)
{
bit.init();
for (int i=n; i>=0; i--)
{
f[i]=bit.query(key(s[i]+k))+1;
bit.update(key(s[i]), f[i]);
}
return f[0]>m;
}
int main()
{
// freopen("1004.in", "r", stdin);
// freopen("1004.out", "w", stdout);
int T=read();
while (T--)
{
n=read(); m=read();
for (int i=1; i<=n; i++) a[i]=read();
for (int i=1; i<=n; i++) sub[i]=s[i]=s[i-1]+a[i];
discretize();
ll l=-1ll*n*MAXV, r=MAXV;
while (l<r)
{
ll mid=(l+r)>>1;
if (check(mid)) r=mid;
else l=mid+1;
}
printf("%lld\n", l);
}
return 0;
}