D. Running Miles
There is a street with $n$ sights, with sight number $i$ being $i$ miles from the beginning of the street. Sight number $i$ has beauty $b_i$. You want to start your morning jog $l$ miles and end it $r$ miles from the beginning of the street. By the time you run, you will see sights you run by (including sights at $l$ and $r$ miles from the start). You are interested in the $3$ most beautiful sights along your jog, but every mile you run, you get more and more tired.
So choose $l$ and $r$, such that there are at least $3$ sights you run by, and the sum of beauties of the $3$ most beautiful sights minus the distance in miles you have to run is maximized. More formally, choose $l$ and $r$, such that $b_{i_1} + b_{i_2} + b_{i_3} - (r - l)$ is maximum possible, where $i_1, i_2, i_3$ are the indices of the three maximum elements in range $[l, r]$.
Input
The first line contains a single integer $t$ ($1 \leq t \leq 10^5$) — the number of test cases.
The first line of each test case contains a single integer $n$ ($3 \leq n \leq 10^5$).
The second line of each test case contains $n$ integers $b_i$ ($1 \leq b_i \leq 10^8$) — beauties of sights $i$ miles from the beginning of the street.
It's guaranteed that the sum of all $n$ does not exceed $10^5$.
Output
For each test case output a single integer equal to the maximum value $b_{i_1} + b_{i_2} + b_{i_3} - (r - l)$ for some running range $[l, r]$.
Example
input
8 1 22 299999996
output
8 1 22 299999996
Note
In the first example, we can choose $l$ and $r$ to be $1$ and $5$. So we visit all the sights and the three sights with the maximum beauty are the sights with indices $1$, $3$, and $5$ with beauties $5$, $4$, and $3$, respectively. So the total value is $5 + 4 + 3 - (5 - 1) = 8$.
In the second example, the range $[l, r]$ can be $[1, 3]$ or $[2, 4]$, the total value is $1 + 1 + 1 - (3 - 1) = 1$.
解题思路
比赛的时候写了个假双指针的做法,然后动态规划又没想到怎么做。其实只要想到把公式变一下就能做出来了。
首先根据贪心思想,对于区间$[l,r]$,若要让$b_{i_1} + b_{i_2} + b_{i_3} - (r - l)$取到最大值,那么其中两个最大元素必然在区间的两个端点,即$a_l, a_r \in \{ {b_{i_1}, b_{i_2}, b_{i_3}} \}$。否则我们可以通过右移左端点$l$或者左移右端点$r$,使得$[l,r]$中的$b_{i_1}, b_{i_2}, b_{i_3}$不变,而$r-l$变小,那么$b_{i_1} + b_{i_2} + b_{i_3} - (r - l)$就会变大。
因此,不失一般性,我们假设$i_1 = l$,$i_3 = r$,$i_2 = i \in (l,r)$,那么公式就会变成$b_l + b_i + b_r - (r-l) = a_i + (a_l + l) + (a_r - r)$。可以发现$a_l + l$的取值仅取决于$l$,$a_r - r$的取值仅取决于$r$,因此可以枚举中间元素$a_i$,然后在$l \in [1, i-1]$中求$a_l + l$的最大值,在$r \in [i+1, n]$中求$a_r - r$的最大值。前后缀的最大值可以预处理出来。
AC代码如下,时间复杂度为$O(n)$:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5 + 10, INF = 0x3f3f3f3f; 5 6 int a[N]; 7 int l[N], r[N]; 8 9 void solve() { 10 int n; 11 scanf("%d", &n); 12 l[0] = r[n + 1] = -INF; 13 for (int i = 1; i <= n; i++) { 14 scanf("%d", a + i); 15 l[i] = max(l[i - 1], a[i] + i); 16 } 17 for (int i = n; i; i--) { 18 r[i] = max(r[i + 1], a[i] - i); 19 } 20 int ret = 0; 21 for (int i = 1; i <= n; i++) { 22 ret = max(ret, a[i] + l[i - 1] + r[i + 1]); 23 } 24 printf("%d\n", ret); 25 } 26 27 int main() { 28 int t; 29 scanf("%d", &t); 30 while (t--) { 31 solve(); 32 } 33 34 return 0; 35 }
参考资料
Codeforces Round #870 (Div. 2) Editorial:https://codeforces.com/blog/entry/115892
标签:10,run,int,sights,leq,Running,miles,Miles From: https://www.cnblogs.com/onlyblues/p/17375929.html