que
Que
【Description】
给出一个n个数组成的序列,这n个数的值∈[1,m],对于一段区间,如果其中值的种类数为K,那么我们称这段区间的价值为K2。请将序列进行合适的划分,使得总价值最小。总价值为各段价值之和。
【Input Format】
第一行两个数n,m。
接下来n行,每行一个数,表示序列中每个数的值。
【Output Format】
一个数,表示总价值。
【Sample Input】
13 4
1
2
1
3
2
2
3
4
3
4
3
1
4
【Sample Output】
11
分析:这道题的解法其实挺巧妙的。
尤其是下面程序中的对q,p数组的维护部分,
采用动态更新的方法,
我也是单步执行了好久才看出一点端倪。。。
(注:q[i]表示从当前点开始向左种数为i的最长区间的左端点位置,
p[i]表示当前点前i这个值出现的最靠右位置,
这两个数组互相动态更新)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | program que; var q: array [ 0..250 ] of longint ; a,p,f: array [ 0..40005 ] of longint ; tmp,tail,i,j,k,n,m,len: longint ; vv: boolean ; function min(x,y: longint ): longint ; begin if x<y then exit(x); exit(y); end ; begin assign(input, 'que.in' ); reset(input); assign(output, 'que.out' ); rewrite(output); readln(n,m); for i:= 1 to n do begin read(a[i]); f[i]:=maxlongint>> 1 ; end ; len:=trunc(sqrt(n)); f[ 0 ]:= 0 ; tail:= 1 ; q[ 1 ]:= 1 ; f[ 1 ]:= 1 ; p[a[ 1 ]]:= 1 ; for i:= 2 to n do begin k:=i; for j:= 1 to tail do if q[j]>p[a[i]] then begin tmp:=q[j]; q[j]:=k; k:=tmp; end else break; if (tail<len) and (q[tail]>p[a[i]]) then begin inc(tail); q[tail]:=k; end ; p[a[i]]:=i; for j:= 1 to tail do f[i]:=min(f[i],f[q[j]- 1 ]+j*j); end ; writeln (f[n]); close(input); close(output); end . |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?