Interviewe HDU - 3486【线段树+二分搜索】

题目连接


  题意是这样说的,有N个人去面试,他们有各自的价值,然后大BOSS又比较的忙,所以想要派出M个小老板去审核这几个面试的小老弟,但是每个小老板只能够选出一个人来,就问要达到价值K,需要几个小老板选出的最出色的小老弟。

  看到这道题之后,我就想,我们可以用线段树来找区间最大值,然后二分搜索去逼近最真实的答案,然后去敲了,就这样过了,不过好像有点卡的成分在里面,不知道其他人是用什么方法过的(毕竟这道题挂出来是挂在图论下的......)。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN=200005;
int N, K;
ll a[maxN], pre, tree[maxN<<2];
void buildTree(int rt, int l, int r)
{
    if(l == r)
    {
        tree[rt] = a[l];
        return;
    }
    int mid = (l + r)>>1;
    buildTree(rt<<1, l, mid);
    buildTree(rt<<1|1, mid+1, r);
    tree[rt] = max(tree[rt<<1], tree[rt<<1|1]);
}
ll query(int rt, int l, int r, int ql, int qr)
{
    if(ql<=l && qr>=r) return tree[rt];
    if(l == r) return tree[rt];
    int mid = (l + r)>>1;
    if(ql>mid) return query(rt<<1|1, mid+1, r, ql, qr);
    else if(qr<=mid) return query(rt<<1, l, mid, ql, qr);
    else
    {
        ll ans = query(rt<<1|1, mid+1, r, mid+1, qr);
        ans = max(ans, query(rt<<1, l, mid, ql, mid));
        return ans;
    }
}
int main()
{
    while(scanf("%d%d", &N, &K)!=EOF)
    {
        pre = 0;
        if(N<0 && K<0) break;
        for(int i=1; i<=N; i++)
        {
            scanf("%lld", &a[i]);
            pre += a[i];
        }
        if(pre <= K) { printf("-1\n"); continue; }
        buildTree(1, 1, N);
        int L=1, R=N, mid=0, ans=N;
        while(L <= R)
        {
            mid = (L + R)>>1;
            ll tmp = 0;
            int up = N/mid;
            for(int i=1; i<=mid; i++)
            {
                tmp += query(1, 1, N, (i-1)*up+1, i*up);
            }
            if(tmp > K) { R=mid-1; ans=mid; }
            else L = mid + 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值