http://acm.hdu.edu.cn/showproblem.php?pid=6606
题意:就是必须吧前面的分成k部分,然后求最大值的最小值,后面的可以不用管。
做法:根据题解上的,二分答案,然后考虑动态规划去判断,dp[i]表示前i个在当前情况下,可以分成几个部分,然后vis表示j这个位置的前面的数一定使用了的。
暴力可能就是这样写,但不过会T,然后考虑数据结构维护,因为,线段树要离散化,而且我不想写,所以直接套了一个二叉树。
时间还可以。时间复杂度
#include "bits/stdc++.h"
using namespace std;
const double eps = 1e-8;
#define reg register
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define makp make_pair
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const ll N = 200000 + 10;
const int M = 1000 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 1000000000 + 7;
struct Treap {
int l, r;
int dat, d, m;
ll val;
} t[N << 2];
int n, k, dp[N], tot, root;
ll a[N], sum[N];
void init() { tot = 0; }
int newnode(ll val, int d) {
t[++tot].val = val, t[tot].dat = rand();
t[tot].d = t[tot].m = d;
t[tot].l = t[tot].r = 0;
return tot;
}
void update(int p) {
if (t[p].l == 0)t[t[p].l].m = -1;
if (t[p].r == 0)t[t[p].r].m = -1;
int tmp = max(t[t[p].l].m, t[t[p].r].m);
t[p].m = max(t[p].d, tmp);
}
void build() {
newnode(-inf, 0), newnode(inf, 0);
root = 1, t[1].r = 2, update(root);
}
void zig(int &p) {
int q = t[p].l;
t[p].l = t[q].r, t[q].r = p, p = q;
update(t[p].r), update(p);
}
void zag(int &p) {
int q = t[p].r;
t[p].r = t[q].l, t[q].l = p, p = q;
update(t[p].l), update(p);
}
void Insert(int &p, ll val, int d) {
if (p == 0) {
p = newnode(val, d);
return;
}
if (val == t[p].val) {
///t[p].cnt++;
t[p].d = max(t[p].d, d);
t[p].m = max(t[p].m, d);
update(p);
return;
}
if (val < t[p].val) {
Insert(t[p].l, val, d);
if (t[p].dat < t[t[p].l].dat) zig(p);
} else {
Insert(t[p].r, val, d);
if (t[p].dat < t[t[p].r].dat) zag(p);
}
update(p);
}
int Getmax(int p, ll val) {
if (p == 0) return -1;
int ans = -1;
if (val == t[p].val) {
ans = max(ans, t[p].d);
if (t[p].r != 0) ans = max(ans, t[t[p].r].m);
} else if (val > t[p].val) {
ans = max(Getmax(t[p].r, val), ans);
} else {
ans = max(ans, t[p].d);
if (t[p].r != 0) ans = max(ans, t[t[p].r].m);
ans = max(ans, Getmax(t[p].l, val));
}
return ans;
}
int judge(ll x) {
int vmx = 0;
init();
root = newnode(0, 0);
for (int i = 1; i <= n; i++) {
ll tmp = sum[i] - x;
int tp = Getmax(root, tmp);
if (tp == -1) Insert(root, sum[i], -1);
else Insert(root, sum[i], ++tp);
vmx = max(vmx, tp);
if (vmx >= k) return 1;
}
return 0;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
sum[0] = 0;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
ll l = -1e15, r = 1e15, ans;
while (l <= r) {
ll mid = (l + r) >> 1;
if (judge(mid)) {
ans = mid;
r = mid - 1;
} else l = mid + 1;
}
cout << ans << endl;
}
return 0;
}