Interviewe HDU - 3486【線段樹+二分搜尋】
阿新 • • 發佈:2018-11-20
題目連線
題意是這樣說的,有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; }