题意
给你一个长度为 n n n的整数数组 a a a。
在一次操作中,你
- 选择一个索引 i i i,使得 1 ≤ i ≤ n − 1 1 \le i \le n - 1 1≤i≤n−1 和 a i ≤ a i + 1 a_i \le a_{i + 1} ai≤ai+1。
- 用 1 1 1增加 a i a_i ai。
求最多进行 k k k次这一运算后所得到的 max ( a 1 , a 2 , … a n ) \max(a_1, a_2, \ldots a_n) max(a1,a2,…an)的最大可能值。
输入
每个测试包含多个测试用例。第一行输入包含一个整数 t t t( 1 ≤ t ≤ 100 1 \le t \le 100 1≤t≤100)–测试用例数。测试用例说明如下。
每个测试用例的第一行包含两个整数 n n n和 k k k( 2 ≤ n ≤ 1000 2 \le n \le 1000 2≤n≤1000, 1 ≤ k ≤ 1 0 8 1 \le k \le 10^{8} 1≤k≤108)–数组的长度 a a a和可执行的最大操作数。
每个测试用例的第二行包含 n n n个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an( 1 ≤ a i ≤ 1 0 8 1 \le a_i \le 10^{8} 1≤ai≤108)–数组 a a a的元素。
保证所有测试用例的 n n n之和不超过 1000 1000 1000。
输出
对每个测试用例输出一个整数,即执行最多 k k k次操作后数组可能的最大值。
思路
二分出数组中每个元素的最大值,然后对这些最大值取个 m a x max max.
思路很清楚,关键是check函数怎么写.
首先我们先假设 x x x是数组中某个元素的最大值,那么我们怎么样才能用最小的代价 c n t cnt cnt才能得到它呢?用贪心的思想来说,就是保证后面的数等于前面的数减一,即 a i = a i − 1 − 1 a_{i}=a_{i-1}-1 ai=ai−1−1,但我们要保持a数组不变,所以我们需要开一个b数组作为a数组的副本,然后依次比较一下 a i a_i ai与 b i b_i bi的大小,如果遇到 a i ≥ b i a_i \geq b_i ai≥bi并且 c n t ≤ k cnt\leq k cnt≤k时就可以返回true,否则返回false.
时间复杂度 n 2 n^2 n2 l o g n logn logn
可能有点抽象,还是举个例子吧(语文不太好)
比如
n
=
9
,
k
=
11
,
x
=
8
,
p
o
s
=
4
n=9,k=11,x=8,pos=4
n=9,k=11,x=8,pos=4的时候
数组
a
:
a:
a:
1
,
2
,
3
,
6
,
5
,
4
,
1
,
2
,
4
1 ,2 ,3 ,6 ,5 ,4 ,1, 2, 4
1,2,3,6,5,4,1,2,4
数组
b
:
b:
b:
1
,
2
,
3
,
8
,
7
,
6
,
5
,
4
,
3
1, 2, 3, 8, 7, 6, 5, 4, 3
1,2,3,8,7,6,5,4,3
代价
:
:
:
0
,
0
,
0
,
2
,
2
,
2
,
4
,
2
,
0
0, 0, 0, 2, 2, 2, 4, 2, 0
0,0,0,2,2,2,4,2,0
c
n
t
=
2
+
2
+
2
+
4
+
2
=
12
cnt=2+2+2+4+2=12
cnt=2+2+2+4+2=12
c
n
t
>
k
cnt > k
cnt>k,所以返回false
当
n
=
9
,
k
=
11
,
x
=
8
,
p
o
s
=
2
n=9,k=11,x=8,pos=2
n=9,k=11,x=8,pos=2的时候
数组
a
:
a:
a:
1
,
2
,
3
,
6
,
5
,
4
,
1
,
2
,
4
1 ,2 ,3 ,6 ,5 ,4 ,1, 2, 4
1,2,3,6,5,4,1,2,4
数组
b
:
b:
b:
1
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
1, 8, 7, 6, 5, 4, 3, 2, 1
1,8,7,6,5,4,3,2,1
代价
:
:
:
0
,
6
,
4
,
0
,
0
,
0
,
0
,
0
,
0
0, 6, 4, 0, 0, 0, 0, 0, 0
0,6,4,0,0,0,0,0,0
c
n
t
=
6
+
4
=
10
cnt=6+4=10
cnt=6+4=10
c
n
t
≤
k
cnt\leq k
cnt≤k,所以返回true.
完整代码
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define int long long
const int N = 3e5 + 10, mod = 998244353, M = 2 * N;
typedef pair<int, int> PII;
typedef long long ll;
const int INF_MAX = 0x3f3f3f3f3f3f3f3f;
int a[N], b[N], n, k;
bool check(int x, int pos)
{
b[pos] = x;
for (int i = pos + 1; i <= n; i++)b[i] = b[i - 1] - 1;
int cnt = 0;
for (int i = pos; i <= n; i++)
{
if (a[i] >= b[i])
{
if (cnt <= k)return true;
else return false;
}
cnt += b[i] - a[i];
}
return false;
}
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)cin >> a[i];
int ans = *max_element(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
{
int l = a[i], r = a[i] + k;
while (l <= r)
{
int mid = (l + r) / 2;
if (check(mid, i))
{
ans = max(mid, ans);
l = mid + 1;
}
else r = mid - 1;
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)solve();
return 0;
}