Bzoj P3613 [Heoi2014]南园满地堆轻絮___贪心

206 篇文章 0 订阅
45 篇文章 0 订阅

题目大意:

一个有 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 &lt; n 1≤i&lt;n 1i<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=MaxA[j]B[j],1jn尽量小。
问最小的 a n s ans ans是多少。

n ≤ 5000000 n≤5000000 n5000000

分析:

对于当前的 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,i1]),满足 n u m &gt; a i num&gt;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 (numai+1)/2
m a x max max{ ( n u m − a i + 1 ) / 2 (num-a_i+1)/2 (numai+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;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值