トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=6606
二分答えを考えてみましょう、我々半値\(X \) 、そして答えは実現可能であることを確認する方法に、DPを解決して考えると、聞かせて\(DP [I] \)最初のi番目の答えでため\(X \)がで最もアップグループの数を除算し、もし\(DP [n]を\ GEQ K \) 次に、X可能で、それは明らかである\(Xの\)は、二つの点単調です。
\ [DP [I] =最大
(DP [J])+ 1(和[I] -和[J-1] \当量X)\] 暴力の直接使用は、列挙された場合のその後複雑\(O(N ^ 2 )\) 、個別のセグメントツリーの後に正しい値の構築を検討。我々は、すべての\(合計[I] \)から与えられたラベルの後に離散化、\(I = 1 \)横断\(N- \)それぞれについて、私は、唯一見つける必要があるプロセスを、\(和[T] \のGEQの合計は、[I] - X \) される(和[I] -x \ \ ) 後継。セグメントツリーでは、重みは、クエリ要求取ら\([T、M] \ ) 最大であることができるが、\(M \)ノードの数は、セグメントツリーの重量です。時間複雑\(O(nlog ^ 2n個) \)
#include <bits/stdc++.h>
#define pii pair<ll, ll>
#define pil pair<ll, long long>
#define pll pair<long long, long long>
#define lowbit(x) ((x)&(-x))
#define mem(i, a) memset(i, a, sizeof(i))
#define sqr(x) ((x)*(x))
#define all(x) x.begin(),x.end()
#define ls (k << 1)
#define rs (k << 1 | 1)
using namespace std;
typedef long long ll;
template <typename T>
inline void read(T &X) {
X = 0; char ch = 0; T op = 1;
for(; ch > '9' || ch < '0'; ch = getchar())
if(ch == '-') op = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar())
X = (X << 3) + (X << 1) + ch - 48;
X *= op;
}
const ll INF = 0x3f3f3f3f;
const ll N = 2e5 + 5;
vector<ll> v;
struct node {
ll l,r,w = 0;
}tr[N * 4];
ll a[N],sum[N];
ll n,k,m;
void build(ll k, ll l, ll r) {
tr[k].l = l; tr[k].r = r;
if(l == r) {
tr[k].w = 0; return;
}
ll mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
tr[k].w = 0;
}
void update(ll k, ll p, ll x) {
ll l = tr[k].l, r = tr[k].r;
ll mid = l + r >> 1;
if(l == r) {tr[k].w = max(tr[k].w, x); return;}
if(p <= mid) update(ls, p, x);
else update(rs, p, x);
tr[k].w = max(tr[ls].w, tr[rs].w);
}
ll query(ll k, ll s, ll t) {
ll l = tr[k].l, r = tr[k].r;
if(s <= l && t >= r) {
return tr[k].w;
}
ll ans = 0;
ll mid = l + r >> 1;
if(s <= mid) ans = max(ans, query(ls, s, t));
if(t > mid) ans = max(ans, query(rs, s, t));
return ans;
}
bool check(ll x) {
build(1, 1, m);
for(ll i = 1; i <= n; i++) {
ll l = lower_bound(all(v), sum[i] - x) - v.begin() + 1;
ll r = lower_bound(all(v), sum[i]) - v.begin() + 1;
//cout << l << " " << r << " " << i << "\n";
if(l > m) {
if(sum[i] <= x) update(1, r, 1);
continue;
}
ll w = query(1, l, m);
if(w) {
update(1, r, w + 1);
} else if(sum[i] <= x) {
update(1, r, 1);
}
}
// cout << query(1, 1, m) << " " << x << "\n";
return query(1, 1, m) >= k;
}
int main() {
#ifdef INCTRY
freopen("input.txt", "rt", stdin);
#endif
ll t;
cin >> t;
while(t--) {
read(n); read(k);
ll mi = -INF, mx = INF;
v.clear();
for(ll i = 1; i <= n; i++) {
read(a[i]); sum[i] = sum[i - 1] + a[i];
v.push_back(sum[i]);
}
sort(all(v)); v.erase(unique(all(v)), v.end());
m = v.size();
/* for(ll i = 1; i <= n; i++) {
id[i] = lower_bound(all(v), sum[i]) - v.begin() + 1;
}*/
ll l = -1e14-10, r = 1e14+10;
ll ans = 0;
while(l <= r) {
ll mid = l + r >> 1;
//cout << mid << "\n";
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
//cout << query(1, 1, m) << " " << k << "\n";
cout << ans << "\n";
}
#ifdef INCTRY
cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}