1248. 灵能传输
灵能传输
思路
1.观察发现每次对一个圣堂武士
a
i
a_{i}
ai一次灵能传输都是对前缀和
S
i
−
1
S_{i - 1}
Si−1,
S
i
S_{i}
Si得一次交换
2.问题转换为
m
a
x
(
S
i
−
S
i
−
1
)
max(S_{i} - S_{i - 1})
max(Si−Si−1)的最小值
3.贪心策略可知只有当
S
S
S单调时才能使得
m
a
x
(
S
i
−
S
i
−
1
)
max(S_{i} - S_{i - 1})
max(Si−Si−1)最小
4.由于题目条件使得
S
0
S_{0}
S0 和
S
n
S_{n}
Sn 得位置固定不变,但是
S
0
S_{0}
S0 和
S
n
S_{n}
Sn不一定是最大值或者最小值,所以贪心策略发生改变
样例输入:
3
4
-1 -2 -3 7
4
2 3 4 -8
5
-1 -1 6 -1 -1
样例输出:
5
7
4
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 300010;
int n;
LL a[N], s[N];
bool st[N];
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
scanf("%d", &n);
s[0] = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%lld", &a[i]);
s[i] = s[i - 1] + a[i];
}
LL s0 = s[0], sn = s[n];
if (s0 > sn) swap(s0, sn);
sort(s, s + n + 1);
for (int i = 0; i <= n; i ++ )
if (s[i] == s0)
{
s0 = i;
break;
}
for (int i = n; i >= 0; i -- )
if (s[i] == sn)
{
sn = i;
break;
}
memset(st, 0, sizeof st);
int l = 0, r = n;
for (int i = s0; i >= 0; i -= 2)
{
a[l ++ ] = s[i];
st[i] = true;
}
for (int i = sn; i <= n; i += 2)
{
a[r -- ] = s[i];
st[i] = true;
}
for (int i = 0; i <= n; i ++ )
if (!st[i])
a[l ++ ] = s[i];
LL res = 0;
for (int i = 1; i <= n; i ++ ) res = max(res, abs(a[i] - a[i - 1]));
printf("%lld\n", res);
}
return 0;
}