题目大意:
一个有
n
n
n个正整数的数列
A
[
1
]
…
A
[
n
]
A[1]…A[n]
A[1]…A[n],
目标是求另一个正整数数列
B
[
1
]
…
B
[
n
]
B[1]…B[n]
B[1]…B[n],使得对于任意的
1
≤
i
<
n
1≤i<n
1≤i<n 有
B
[
i
]
≤
B
[
i
+
1
]
B[i] ≤B[i+1]
B[i]≤B[i+1],
而且使得
A
n
s
=
M
a
x
∣
A
[
j
]
−
B
[
j
]
∣
,
1
≤
j
≤
n
Ans = Max{|A[j]-B[j]|,1≤j≤n}
Ans=Max∣A[j]−B[j]∣,1≤j≤n尽量小。
问最小的
a
n
s
ans
ans是多少。
n ≤ 5000000 n≤5000000 n≤5000000
分析:
对于当前的
a
i
a_i
ai而言,假如存在
n
u
m
=
m
a
x
(
a
j
)
(
j
∈
[
1
,
i
−
1
]
)
num=max(a_j)(j∈[1,i-1])
num=max(aj)(j∈[1,i−1]),满足
n
u
m
>
a
i
num>a_i
num>ai,那么我们对于
n
u
m
num
num所在的位置
k
k
k而言,在
[
k
,
i
]
[k,i]
[k,i]间的数必定都要改成严格不下降的序列,那么此时改成
(
n
u
m
+
a
i
)
/
2
(num+a_i)/2
(num+ai)/2显然代价最优,代价为
(
n
u
m
−
a
i
+
1
)
/
2
(num-a_i+1)/2
(num−ai+1)/2
取
m
a
x
max
max{
(
n
u
m
−
a
i
+
1
)
/
2
(num-a_i+1)/2
(num−ai+1)/2 } 即可
时间复杂度:
O
(
n
)
O(n)
O(n)
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define N 5000005
using namespace std;
typedef long long ll;
ll A[N], Sa, Sb, Sc, Sd, MOD;
int n;
ll Uddnum(ll x)
{
return (((Sa * x % MOD * x % MOD * x % MOD + Sb * x % MOD * x % MOD) % MOD + Sc * x % MOD) % MOD + Sd) % MOD;
}
int main()
{
scanf("%d %lld %lld %lld %lld %lld %lld", &n, &Sa, &Sb, &Sc, &Sd, &A[1], &MOD);
A[0] = 0; A[1] %= MOD;
ll maxnum = 0, ans = 0;
for (int i = 1; i <= n; i++)
{
if (i >= 2) A[i] = (Uddnum(A[i - 1]) + Uddnum(A[i - 2])) % MOD;
if (maxnum > A[i]) ans = max(ans, (maxnum - A[i] + 1) / 2);
maxnum = max(maxnum, A[i]);
}
printf("%lld\n", ans);
return 0;
}