环中环 纪中1347 dp+线段树优化 玄学
2016-08-16 16:47
399 查看
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.
相关文章推荐
- Codeforces Round #271 (Div. 2)E. Pillars(dp+线段树优化)
- Contest20140906 ProblemA dp+线段树优化
- ZOJ 3349 Special Subsequence【dp+线段树优化】
- #Poj1769#Minimizing maximizer(Dp+线段树优化)
- ZOJ 3349 Special Subsequence(DP+线段树优化)
- hdu 3450 离散化+dp+线段树优化
- poj 3171 dp+线段树优化
- CodeForces 833B The Bakery(dp+线段树优化)
- [线段树][读入优化][玄学加速]借教室 noip
- bzoj1835 [ZJOI2010]base 基站选址(dp+线段树优化)
- dp+线段树优化-hdu-3698-Let the light guide us
- UVA-1322 Minimizing Maximizer (DP+线段树优化)
- [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)
- HDU 5125 magic balls(dp+线段树优化)
- ZOJ 3349 Special Subsequence(DP+线段树优化)
- HDU 4521 小明系列问题——小明序列【dp+线段树优化||最长递增序列】
- 洛谷P3994 Highway(树形DP+斜率优化+可持久化线段树/二分)
- 1376 最长递增子序列的数量(dp+线段树优化)
- Acdream 1126 Beautiful People(最长上升子序列,dp+线段树优化)
- 【DP+线段树优化】[CQBZOJ2933]数据