抓知了

题目

深海龙王和水葫芦娃放了暑假闲的无聊,一天他们路过一棵树,听到树上的知了叫的好欢啊∼
深海龙王准备抓几只知了送给水葫芦娃。他发现面前的这棵树是一颗以1 号节点为根节点的一颗有根树,同时他又发现这颗树上的每一个节点i 上都恰好停有一只蝉,正在愉快的以ai 的响声鸣叫∼
深海龙王会从1 号节点起沿着树边一直爬,直到爬到一个叶子节点(请不要在意他怎么下来),在这途中他可以选择一些他经过的蝉并将它们抓起来。但是水葫芦娃希望深海龙王抓的知了能发出越来越响的鸣叫声,起码得要单调不减!

题意

给你一颗树(n<=100000),让你求上面的最长不下降子序列。

分析

其实不要被树吓到了,这是一道简单题,我们仍然可以用nlogn的方法去做这道题。
我们可以从根开始做,然后每次更新每个节点的时候递归下去
递归完后,就可以直接去把值还原。
在这里,顺便补充一下,如何nlogn求最长不下降子序列:
我们可以发现,原来的dp方程f[i]=f[j]+1,中a[j]的值,
我们想保留j,仅当f[j]最大时,a[j]最小(我们可以贪心的想,这样可以为后面贡献更大)
于是我们便可以接着根据这个思路接着想下去:
从头开始枚举,设答案是ans,f[k]表示答案为k时最小的a[j]的值是多少。
那么若枚举的a[i]>f[ans]那么ans++,f[ans]=a[i];
上面便表示a[i]可以对答案做出贡献,那么若不能大于呢?它还有没有贡献呢?其实还是一样是有的!
我们二分出最大的k,使得f[k]<a[i],当然f数组是具有递增性质的



function search(x,y:longint):longint;
var mid,l,r,ty:longint;
begin
    l:=1;r:=x;
    while l<r do begin
        mid:=(l+r)shr 1;
        if f[mid]<=y then l:=mid+1 else r:=mid;
    end; exit(l);
end;
    for i:=1 to num do begin
        if a[i]>f[we] then begin
           inc(we);f[we]:=a[i];
        end else begin
           sd:=search(we,a[i]);
           f[sd]:=min(f[sd],a[i]);
        end;
    end;

(很明显,f[u]表示的是答案为u的a的值,f[u+1]若存在,那么必定是大于前面一个的最小值的)
但是还要注意f[i]的值实际上是不合法的(也就是说这种方法只限用于求答案,但是不求具体的每个值)请读者自己思考!

代码

type
   arr=array[1..100005] of longint;
var
    n,x,i,nu,ans:longint;
    last,next,b:array[1..100005] of longint;
    a,f:array[1..100005] of longint;
procedure insert(x,y:longint);
begin
    inc(nu);
    b[nu]:=y;
    next[nu]:=last[x];
    last[x]:=nu;
end;
function search(x,y:longint):longint;
var mid,l,r,ty:longint;
begin
    l:=1;r:=x;ty:=0;
    while l<r do begin
        mid:=(l+r)shr 1;
        if f[mid]<=y then l:=mid+1 else r:=mid;
        inc(ty);
    end; exit(l);
end;
function min(l,r:longint):longint;
begin
   if l<r then exit(l) else exit(r);
end;
function max(l,r:longint):longint;
begin
   if l<r then exit(r) else exit(l);
end;
procedure dfs(x,we:longint);
var p,pe,po,lie,op:longint;
begin
    p:=last[x];
    while p<>0 do begin
        if a[b[p]]>=f[we] then begin
           pe:=we+1;
           po:=f[we];op:=we;
           f[pe]:=a[b[p]];
        end else begin
           lie:=search(we,a[b[p]]);
           pe:=we;po:=f[lie];op:=lie;
           f[lie]:=min(f[lie],a[b[p]]);
        end;
        dfs(b[p],pe);
        f[op]:=po;
        p:=next[p];
    end;
    ans:=max(ans,we);
end;
begin
assign(input,'cicada.in');reset(input);
assign(output,'cicada.out');rewrite(output);
    readln(n);
    for i:=2 to n do begin
        read(x);
        insert(x,i);
    end;
    fillchar(f,sizeof(f),128);
    for i:=1 to n do read(a[i]);
    f[1]:=a[1];
    dfs(1,1);
    writeln(ans);
close(input);close(output);
end.
乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值