Codeforces Round #353 (Div. 2) E. Trains and Statistic (线段树 + dp)

题目链接:http://codeforces.com/contest/675/problem/E

你可以从第 i 个车站到 [i + 1, a[i]] 之间的车站花一张票。

p[i][j]表示从 i 到 j 最少花费多少张票,问你 ∑p[i][j] (1<=i<j<=n) 是多少。

 

设dp[i]表示 i 到 [i+1, n] 总共花费的票。

已知 i 到 [i + 1, a[i]] 只要一张票就可以了。那么要是求i 到 大于a[i]的车站要多少票呢,这肯定需要一个[i + 1, a[i]] 最优的车站作为转移车站,那最优的肯定是a[temp]值最大的。

那么a[i] = a[temp] + (n - i) - (a[i] - temp) , temp表示[i+1 , a[i]]中a[j]最大的下标。

求区间最大线段树就行了,具体看代码。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef __int64 LL;
 4 typedef pair <int , int> P; //first表示a[i]大小, second表示下标
 5 const int MAXN = 1e5 + 5;
 6 struct segtree {
 7     int l , r , val , pos;
 8 }T[MAXN << 2];
 9 int a[MAXN];
10 LL dp[MAXN];
11 
12 void build(int p , int l , int r) {
13     int mid = (l + r) >> 1;
14     T[p].l = l , T[p].r = r;
15     if(l == r) {
16         T[p].val = a[l];
17         T[p].pos = l;
18         return ;
19     }
20     build(p << 1 , l , mid);
21     build((p << 1)|1 , mid + 1 , r);
22     if(T[p << 1].val >= T[(p << 1)|1].val) {
23         T[p].val = T[p << 1].val;
24         T[p].pos = T[p << 1].pos;
25     }
26     else {
27         T[p].val = T[(p << 1)|1].val;
28         T[p].pos = T[(p << 1)|1].pos;
29     }
30 }
31 
32 P query(int p , int l , int r) {
33     int mid = (T[p].l + T[p].r) >> 1;
34     if(T[p].l == l && T[p].r == r) {
35         return make_pair(T[p].val , T[p].pos);
36     }
37     if(r <= mid) {
38         return query(p << 1 , l , r);
39     }
40     else if(l > mid) {
41         return query((p << 1)|1 , l , r);
42     }
43     else {
44         P tmp1 = query(p << 1 , l , mid) , tmp2 = query((p << 1)|1 , mid + 1 , r);
45         return tmp1.first > tmp2.first ? tmp1 : tmp2;
46     }
47 }
48 
49 int main()
50 {
51     int n;
52     scanf("%d" , &n);
53     for(int i = 1 ; i <= n - 1 ; ++i) {
54         scanf("%d" , a + i);
55     }
56     a[n] = n;
57     build(1 , 1 , n);
58     LL res = 0;
59     for(int i = n - 1 ; i >= 1 ; --i) {
60         int Max_pos = query(1 , i + 1 , a[i]).second;
61         dp[i] = dp[Max_pos] + (n - i) - (a[i] - Max_pos);
62         res += dp[i];
63     }
64     printf("%lld\n" , res);
65     return 0;
66 }

 

posted @ 2016-06-21 22:24  Recoder  阅读(162)  评论(0编辑  收藏  举报