Topic link: http://acm.hdu.edu.cn/showproblem.php?pid=6606
Considering the dichotomous answer, we divide a value of (x\), then how to verify the feasibility of the answer? Considering the DP solution, let(dp[i]) be the first one and divide up the maximum number of groups with the answer of (x), then if\(dp[n]geq k\ is feasible, it is obvious that\(x\) is monotonous, so dichotomous.
\[dp[i] = max(dp[j]) + 1 (sum[i] - sum[j-1] \leq x)\]
If violence enumeration is used directly, the complexity O(n^2) may be considered to construct weighted segment trees after discretization. After we discretize all (sum[i] given labels, we start traversing from \(i=1\) to (n\) and only need to find the first \(sum[t]geq[sum]-x\ for each i, that is, the successor of \(sum[i]-x\. Then query is used to find the maximum value of ([t, m]), \ is the number of nodes in the weighted segment tree. Time Complexity(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; }