G2. Teleporters (Hard Version)

G2. Teleporters (Hard Version)

The only difference between the easy and hard versions are the locations you can teleport to.

Consider the points $0,1,\dots,n+1$ on the number line. There is a teleporter located on each of the points $1,2,\dots,n$. At point $i$, you can do the following:

  • Move left one unit: it costs $1$ coin.
  • Move right one unit: it costs $1$ coin.
  • Use a teleporter at point $i$, if it exists: it costs $a_i$ coins. As a result, you can choose whether to teleport to point $0$ or point $n+1$. Once you use a teleporter, you can't use it again.

You have $c$ coins, and you start at point $0$. What's the most number of teleporters you can use?

Input

The input consists of multiple test cases. The first line contains an integer $t$ ($1 \leq t \leq 1000$) — the number of test cases. The descriptions of the test cases follow.

The first line of each test case contains two integers $n$ and $c$ ($1 \leq n \leq 2\cdot10^5$; $1 \leq c \leq 10^9$) — the length of the array and the number of coins you have respectively.

The following line contains $n$ space-separated positive integers $a_1,a_2,\dots,a_n$ ($1 \leq a_i \leq 10^9$) — the costs to use the teleporters.

It is guaranteed that the sum of $n$ over all test cases does not exceed $2\cdot10^5$.

Output

For each test case, output the maximum number of teleporters you can use.

Example

input

10
5 6
1 1 1 1 1
8 32
100 52 13 6 9 4 100 35
1 1
5
4 5
4 3 2 1
5 9
2 3 1 4 1
5 8
2 3 1 4 1
4 3
2 3 4 1
4 9
5 4 3 3
2 14
7 5
5 600000000
500000000 400000000 300000000 200000000 100000000

output

2
3
0
1
3
2
1
1
2
2

Note

In the first test case, you can move one unit to the right, use the teleporter at index $1$ and teleport to point $n+1$, move one unit to the left and use the teleporter at index $5$. You are left with $6-1-1-1-1 = 2$ coins, and wherever you teleport, you won't have enough coins to use another teleporter. You have used two teleporters, so the answer is two.

In the second test case, you go four units to the right and use the teleporter to go to $n+1$, then go three units left and use the teleporter at index $6$ to go to $n+1$, and finally, you go left four times and use the teleporter. The total cost will be $4+6+3+4+4+9 = 30$, and you used three teleporters.

In the third test case, you don't have enough coins to use any teleporter, so the answer is zero.

 

解题思路

  与G1. Teleporters (Easy Version)不同,当使用了某个传送器后不仅可以选择传送到下标$0$处,还可以传送到下标$n+1$处。

  很明显,如果当前在$1 \sim n$的某个位置(也就是不是起点$0$),每个传送器的代价为$\min(a_i + i, a_i + n + 1 - i)$,因此为了取到最大数目的传送器就应该按照代价从小到大来选择传送器。

  问题是现在是从$0$点开始,因此会有贪心的思路是从$1 \sim n$中选择最小的$a_i + i$所对应的下标$x$,然后从$0$走到$x$,再按照上面的做法来选择传送器。但这种做法是有问题的,参考下面的数据:

2 14
7 5

  按照上面贪心的思路,$x = 2$,当从$0$走到$x$后还剩下$14 - (5 + 2) = 7$,已经选不了下标$1$处的传送器了。实际上应该取$x = 1$,然后再传送到$n+1$处,这样总代价就是$1 + 7 + 1 + 5 = 14 \leq 14$,最多可以选择$2$个传送器。

  因此贪心是行不通的,那么就直接枚举第一次走到的下标$x$,此时还剩下$m - (a_x + x)$,为了快速求出最多还能选择多少个传送器,我们按照之前的思路求出每个传送器的最小代价$\min(a_i + i, a_i + n + 1 - i)$,然后从小到大排序,再求前缀和,那么就可以二分出来不超过$m - (a_x + x)$的最大值了。剩下的细节见注释。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 typedef pair<int, int> PII;
 6 
 7 const int N = 2e5 + 10;
 8 
 9 PII a[N];
10 LL s[N];
11 
12 void solve() {
13     int n, m;
14     scanf("%d %d", &n, &m);
15     for (int i = 1; i <= n; i++) {
16         int x;
17         scanf("%d", &x);
18         a[i] = {x + min(i, n + 1 - i), x + i};
19     }
20     sort(a + 1, a + n + 1);
21     for (int i = 1; i <= n; i++) {
22         s[i] = s[i - 1] + a[i].first;
23     }
24     int ret = 0;
25     for (int i = 1; i <= n; i++) {    // 枚举第一次到达的下标
26         if (a[i].second <= m) {    // 至少可以选择这个传送器
27             int l = 0, r = n;    // 左端点从0开始,如果最后有l=0意味着不能选择第二个传传送器
28             while (l < r) {
29                 int mid = l + r + 1 >> 1;
30                 LL t = s[mid] + a[i].second;    // 总代价
31                 if (i <= mid) t -= a[i].first;    // 选择的传送器包括了i,应该删除对于的数据
32                 if (t <= m) l = mid;
33                 else r = mid - 1;
34             }
35             ret = max(ret, l + (l < i));    // 如果l<i那么就需要额外加上i这个位置的传送器
36         }
37     }
38     printf("%d\n", ret);
39 }
40 
41 int main() {
42     int t;
43     scanf("%d", &t);
44     while (t--) {
45         solve();
46     }
47     
48     return 0;
49 }

 

参考资料

  Codeforces Round #849 (Div. 4) Editorial:https://codeforces.com/blog/entry/112282

posted @ 2023-02-04 21:56  onlyblues  阅读(155)  评论(0编辑  收藏  举报
Web Analytics