公园里有n棵树,编号从1到n,第i棵树的初始高度为hi。你要给这些树浇水,让它们都长到同样的高度。浇水过程如下。你从第一天开始给树浇水。在第j天你可以:选择一棵树,给它浇水。如果日期是奇数(例如1,3,5,7,…),那么树的高度增加1。如果一天是偶数(例如:2, 4, 6, 8,…),那么树的高度增加2。或者一天不给树浇水。注意,你一天只能给一棵树浇水。你的任务是确定浇水所需的最少天数,这样它们才能长到相同的高度。你必须回答t个独立的测试用例。输入输入的第一行包含一个整数t (1 < t <2-104)——测试用例的数量。测试用例的第一行包含一个整数n (1 < n < 3- 105)——树的数量。测试用例的第二行包含n个整数h1, h2,…, hn (1 < hi < 10°),其中h为第i棵树的高度。它保证所有测试用例的n的和不超过3 - 105 (Sn < 3.105)。输出对于每个测试用例,打印一个整数——浇水所需的最少天数,以使它们长到相同的高度。
Example
input
Copy
3 3 1 2 4 5 4 4 3 5 5 7 2 5 4 8 3 7 4
output
Copy
4 3 16
请注意考虑这个例子的第一个测试用例。树的初始状态为[1,2,4]。1. 在第一天,让我们给第一棵树浇水,这样高度序列就变成[2,2,4];2. 在第二天,让我们给第二棵树浇水,这样高度序列就变成[2,4,4];3.让我们跳过第三天;4. 第四天,我们给第一棵树浇水,这样高度的序列就变成了[4,4,4]。因此,答案是4。
题解:
题意很容易理解,一般这种题就是二分天数,check即可
但是可能会出现一种情况类似这样,
遇到1 1 1 1 1 1 2这种情况我们最少的天数是把2先变成3然后再把所有都变成3,所以我们判断天数能不能把所有数组都变成最大数或者都变成最大数+1,如果能天数就符合。
所以判断时候mx + 1,mx都要判断
并且判断时优先用偶数天数
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define int long long
const int N = 4e5 + 10;
typedef pair<int, int> PII;
int h[N],n;
int check(int one,int two,int x)
{
for(int i = 1;i <= n;i++)
{
if(h[i] < x)
{
int w = x - h[i];
if(w/2 <= two)
{
two -= w/2;
one -= w%2;
}
else
{
w -= two*2;
two = 0;
one -= w;
}
}
}
if(one <0 )
return 0;
else
return 1;
}
void solve()
{
cin >> n;
int l = 0,r = 1e18;
int mx = 0;
for(int i = 1;i <= n;i++)
{
cin >> h[i];
mx = max(mx,h[i]);
}
while(l <= r)
{
int mid = (l + r)/2;
if(check(mid - mid/2,mid/2,mx)||check(mid - mid/2,mid/2,mx + 1))
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
cout <<l <<"\n";
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
//scanf("%lld",&t);
while (t--)
{
solve();
}
}
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//1 1 1 0 1
//0 1 1 1 1
//0 1 1 1 1