HDU 多校第三场Distribution of books

http://acm.hdu.edu.cn/showproblem.php?pid=6606

题意:就是必须吧前面的分成k部分,然后求最大值的最小值,后面的可以不用管。

做法:根据题解上的,二分答案,然后考虑动态规划去判断,dp[i]表示前i个在当前情况下,可以分成几个部分,然后vis表示j这个位置的前面的数一定使用了的。

暴力可能就是这样写,但不过会T,然后考虑数据结构维护,因为,线段树要离散化,而且我不想写,所以直接套了一个二叉树。

时间还可以。时间复杂度O(n*logn*logn)

#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;
}
发布了130 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/97753737
今日推荐