2019牛客暑期多校训练营(第六场) D-Move

https://ac.nowcoder.com/acm/contest/886/D


思路:这题不能用二分,因为是不能证明是单调的,读完题发现跟HUD 2795 好像,就直接用线段树来寻找最小的箱子了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define lson l, m, rt << 1
 4 #define rson m + 1,r, rt << 1 | 1
 5 #define lst rt << 1
 6 #define rst rt << 1 | 1
 7 #define lr2 (l + r) >> 1
 8 const int maxn = 1e4+5;
 9 const int INF = 0x3f3f3f3f;
10 typedef long long ll;
11 int n, k;
12 int a[maxn];
13 int sum[maxn << 2];
14 void up(int rt)
15 {
16     sum[rt] = max(sum[rst],sum[lst]);
17 }
18 void build(int v, int l, int r, int rt)
19 {
20     sum[rt] = v;
21     if(l == r) return;
22     int m = lr2;
23     build(v, lson);
24     build(v, rson);
25 }
26 void query(int x, int l, int r, int rt)
27 {
28     if(l == r)
29     {
30         sum[rt] -= x;
31         return ;
32     }
33     int m = lr2;
34     if(sum[lst] >= x) query(x, lson);
35     else query(x, rson);
36     up(rt);
37     return ;
38 }
39 bool check(int mid)
40 {
41     bool flag = true;
42     build(mid, 1, k, 1);
43     for(int i = n;i >= 1;i--)
44     {
45         if(sum[1] < a[i])
46         {
47             flag = false;
48             break;
49         }
50         else query(a[i], 1, k, 1);
51     }
52     return flag;
53 }
54 int main()
55 {
56     int t;
57     scanf("%d",&t);
58     int cnt = 1;
59     while(t--)
60     {
61         scanf("%d%d",&n,&k);
62         int r = 0;
63         int l = 0;
64         for(int i = 1;i <= n;i++)
65         {
66             scanf("%d",&a[i]);
67             r += a[i];
68             l = max(l,a[i]);
69         }
70         sort(a + 1,a+n +1);
71         l = max(l,r / k);
72         while(!check(l)) l++;
73         printf("Case #%d: %d\n",cnt++,l);
74     }
75     return 0;
76 }


猜你喜欢

转载自www.cnblogs.com/Carered/p/11295881.html