【GDOI2017】最长不下降子序列

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

看到数据范围就应该要很明显地发现找循环节,因为循环节最长只有150个数。
先处理出循环节,然后要开始考虑,在前面还没有开始循环时取若干个数,循环部分选出一个数每一节取,最后一个循环区间再取若干个数。思想很明显了,先做一次最长不下降子序列,再一个个区间添加,当答案增加值只有1时,说明不会再有更优的贡献,然后就能跳过剩下的,把最后一个区间添加进去再求一遍。至此,就能求出答案了。

Code

var
    t,q1,q2,q3,p,x:array[0..1000] of longint;
    d:array[0..1000000] of longint;
    i,a,b,c,mo,s1,s2,s3,wz,tot:longint;
    num,n,ans:int64;
function min(x,y:longint):longint;
begin
    if x<y then exit(x);exit(y);
end;
procedure deal;
var i:longint;
begin
    for i:=1 to s1 do q1[i]:=x[i];
    for i:=1 to s2 do q2[i]:=x[i+s1];
    for i:=1 to s3 do q3[i]:=q2[i];
end;
function ef(x:longint):longint;
var l,r:longint;
begin
    l:=0;r:=ans;
    while l<r do
    begin
        ef:=(l+r+1)div 2;
        if d[ef]<=x then l:=ef else r:=ef-1;
    end;
    exit(l+1);
end;
begin
    readln(n);
    readln(x[1],a,b,c,mo);
    p[x[1]]:=1;
    i:=1;
    while i<n do
    begin
        inc(i);
        x[i]:=(x[i-1]*x[i-1]*a+x[i-1]*b+c) mod mo;
        if p[x[i]]<>0 then
        begin
            s1:=p[x[i]]-1;s2:=i-p[x[i]];s3:=(n-s1) mod s2;
            deal;
            break;
        end;
        p[x[i]]:=i;
    end;
    fillchar(d,sizeof(d),$7f div 2);d[0]:=0;
    if s2=0 then
    begin
        for i:=1 to n do
        begin
            wz:=ef(x[i]); d[wz]:=min(d[wz],x[i]);
            if wz>ans then ans:=wz;
        end;
        writeln(ans);
        exit;
    end;
    for i:=1 to s1 do
        begin
            wz:=ef(q1[i]); d[wz]:=min(d[wz],q1[i]);
            if wz>ans then ans:=wz;
        end;
    num:=(n-s1) div s2;
    while num>0 do
    begin
        dec(num);tot:=ans;
        for i:=1 to s2 do
        begin
            wz:=ef(q2[i]); d[wz]:=min(d[wz],q2[i]);
            if wz>ans then ans:=wz;
        end;
        if ans-tot=1 then break;
    end;
    tot:=ans;
    ans:=ans+num;
    num:=ans;ans:=tot;
    for i:=1 to s3 do
        begin
            wz:=ef(q3[i]); d[wz]:=min(d[wz],q3[i]);
            if wz>ans then ans:=wz;
        end;
    ans:=num+(ans-tot);
    writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值