题意:
a[i]表示从第i个车站可以一张票到第[i+1,a[i]]这些车站;
p[i][j]表示从第i个车站到第j个车站的最少的票数,现在要求∑dp[i][j](1<=i<=n,i<j<=n);
思路:从I开始走,在i+1到a[i]之间一定会到使a[j]最大的j,因为要使步数最小,接下来能走得更快
区间询问最值用RMQ与线段树都可以
dp[i]表示dp[i,i+1],dp[i,i+2]...dp[i,n]这些值的和
dp[i]=dp[k]+(n-i)-(a[i]-k),k为[i+1,a[i]]中使a[k]最大的k
n-i:有dp[i,i+1],dp[i,i+2]...dp[i,n]一共n-i个状态要从i走到k
-(a[i]-k):dp[i,k+1]到 dp[i,a[i]]长度与之前相比没有变化
1 type ok=record
2 s:int64;
3 a:longint;
4 end;
5
6 const oo=1000000000000000;
7
8 var dp:array[0..100000]of int64;
9 a:array[1..100000]of longint;
10 tree:array[1..400000]of ok;
11 n,i,k:longint;
12 ans:int64;
13
14 procedure pushup(p:longint);
15 begin
16 if tree[p<<1].s>tree[p].s then tree[p]:=tree[p<<1];
17 if tree[p<<1+1].s>tree[p].s then tree[p]:=tree[p<<1+1];
18 end;
19
20 procedure build(l,r,p:longint);
21 var mid:longint;
22 begin
23 tree[p].s:=a[l];
24 tree[p].a:=l;
25 if l=r then exit;
26 mid:=(l+r)>>1;
27 build(l,mid,p<<1);
28 build(mid+1,r,p<<1+1);
29 pushup(p);
30 end;
31
32 function query(l,r,x,y,p:longint):ok;
33 var mid:longint;
34 t:int64;
35 q,tmp:ok;
36
37 begin
38 if (l=x)and(r=y) then exit(tree[p]);
39 mid:=(l+r)>>1;
40 t:=0;
41 if (x>=l)and(y<=mid) then
42 begin
43 q:=query(l,mid,x,y,p<<1);
44 if q.s>t then begin t:=q.s; tmp:=q; end;
45 end else
46 if (x>mid)and(y<=r) then
47 begin
48 q:=query(mid+1,r,x,y,p<<1+1);
49 if q.s>t then begin t:=q.s; tmp:=q; end;
50 end else
51 begin
52 q:=query(l,mid,x,mid,p<<1);
53 if q.s>t then begin t:=q.s; tmp:=q; end;
54 q:=query(mid+1,r,mid+1,y,p<<1+1);
55 if q.s>t then begin t:=q.s; tmp:=q; end;
56 end;
57 exit(tmp);
58 end;
59
60 begin
61 //assign(input,'1.in'); reset(input);
62 //assign(output,'1.out'); rewrite(output);
63 readln(n);
64 for i:=1 to n-1 do read(a[i]);
65 a[n]:=n;
66 build(1,n,1);
67
68 for i:=n-1 downto 1 do
69 begin
70 k:=query(1,n,i+1,a[i],1).a;
71 dp[i]:=dp[k]+(n-i)-(a[i]-k);
72 end;
73 for i:=1 to n do ans:=ans+dp[i];
74 writeln(ans);
75 //close(input);
76 //close(output);
77 end.