环中环 纪中1347 dp+线段树优化 玄学

    xiaoxiao2026-08-13  8

    Description

      被认为天才的小头遇到麻烦了!!这天数学课老师给出了一道难题,而小头居然没能在3秒内解决,可见此题难度之大。   问题是这样的:n个整数围成一个环,老师要求选出其中的若干数,使得选中的数所组成的环中,两个相邻数的差的绝对值不等于1。在满足这个前提下,问最多能取多少个数。

    Input

      第一行一个正整数n,表示有n个数   第二行n个整数,a1、a2……an 按顺时针方向围成一个环。

    Output

      一个正整数,即表示最多能选多少个数。

    分析

    用dp[i]表示以第i个数结尾最多能选多少个数。 那我们只能在dp[1]..d[i-1]的范围中找到一个最大的dp[j],且a[j]是在0..a[i]-2,a[i],a[i]+2..max的范围中(因为a[i]-1和a[i]+1与a[i]的差的绝对值等于1)。 输出时输出max(dp[i])。 可以用线段树来优化这一过程(范围找最大)。

    代码

    const maxn=300000; type pnode=^tnode; tnode=record lc,rc:pnode; c,xia:longint; end; var f,s:array[0..maxn] of longint; data:array[0..maxn] of longint; ans:longint; n,m:longint; d:longint; t:pnode; procedure neww(var t:pnode); begin if t=nil then begin new(t); t^.c:=0; t^.lc:=nil; t^.rc:=nil; end; end; procedure insert(var t:pnode; l,r,x,y,co,xi:longint); var i,j,k:longint; mid:longint; begin with t^ do begin if c<co then begin c:=co; xia:=xi; end; mid:=(l+r) div 2; if (l=x) and (r=y) then exit; if (l<=x) and (mid>=y) then begin neww(lc); insert(lc,l,mid,x,y,co,xi); exit; end; if (mid<x) and (r>=y) then begin neww(rc); insert(rc,mid+1,r,x,y,co,xi); exit; end; neww(lc); neww(rc); insert(lc,l,mid,x,mid,co,xi); insert(rc,mid+1,r,mid+1,y,co,xi); end; end; function find(t:pnode;l,r,x,y:longint; var x1:longint):longint; var mid:longint; i,j,k:longint; begin if t=nil then exit(0); if l>r then exit(0); with t^ do begin mid:=(l+r) div 2; if (l=x) and (r=y) then begin find:=c; x1:=xia; exit; end; i:=0; j:=0; if (l<=x) and (mid>=y) then begin find:=find(lc,l,mid,x,y,x1); exit; end; if (mid<x) and (r>=y) then begin find:=find(rc,mid+1,r,x,y,x1); exit; end; i:=find(lc,l,mid,x,mid,x1); k:=0; j:=find(rc,mid+1,r,mid+1,y,k); if i>j then find:=i else begin find:=j; x1:=k; end; end; end; procedure init; var i:longint; begin readln(n); m:=0; for i:=1 to n do begin read(data[i]); data[i+n]:=data[i]; if data[i]>m then m:=data[i]; end; end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure main; var i,j,k,l:longint; x,y,z:longint; ans:longint; begin neww(t); insert(t,1,m,data[1],data[1],1,1); f[1]:=1; s[1]:=1; for i:=2 to n do begin x:=0; y:=0; z:=0; j:=find(t,1,m,1,data[i]-2,x); k:=find(t,1,m,data[i]+2,m,y); l:=find(t,1,m,data[i],data[i],z); f[i]:=max(j,k); f[i]:=max(f[i],l); if f[i]=j then s[i]:=x else if f[i]=k then s[i]:=y else s[i]:=z; if f[i]=0 then s[i]:=i; f[i]:=f[i]+1; insert(t,1,m,data[i],data[i],f[i],s[i]); end; ans:=0; for i:=1 to n do if (ans<f[i]) and (abs(data[s[i]]-data[i])<>1) then ans:=f[i]; write(ans); end; begin init; main; end.
    转载请注明原文地址: https://ju.6miu.com/read-1311154.html
    最新回复(0)