2020/10/30 模拟赛 序列

Description

淘淘在研究极差,即可重集的最大值减最小值(这个定义应该都知道吧)。 蓝蓝有一个数列 $a_1,a_2,cdots ,a_n$。他想考考淘淘是否真的理解了极差,就让淘淘把他划分为若干子区间(可以退化为一个数,但不能退化为空集),并最大化这些子区间极差之和。 由于他的数列太长了,他用某种方法来表示这个序列,详情请见输入格式。 又由于他的数列太长了,他只需要淘淘告诉他这个最大值的和。

Solution

题中要求一个序列划分为数段,每一段的极差之和

发现如果有一段不单调,可以将其划分得到更优的答案;如果一段单调,继续划分不会使答案更优

从前到后扫数组,考虑每一位作为一个单调区间的最小值或最大值两种情况

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,x,y,z,b[10000005],a[10000005],m;
long long ans,maxx,minn;
inline int read()
{
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
int main()
{
    n=read(),x=read(),y=read(),z=read(),b[1]=read(),b[2]=read(),m=read();
    for(int i=3;i<=n;i++)
    {
        b[i]=(1ll*x*b[i-1]+1ll*y*b[i-2]+z)%(1<<30);
    }
    for(int i=1,j=1;i<=m;i++)
    {
        int p=read(),l=read(),r=read();
        while(j<=p)
        {
            a[j]=b[j]%(r-l+1)+l,++j;
        }
    }
    minn=-a[1],maxx=a[1];
    for(int i=1;i<=n;i++)
    {
        ans=max(minn+a[i],maxx-a[i]);
        minn=max(minn,ans-a[i+1]);
        maxx=max(maxx,ans+a[i+1]);
    }
    printf("%lld
",ans);
    return 0;
}
序列
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13956230.html