题意:有n个车站,第i个车站可以买一张票到i+1和ai之间,p(i,j)表示从i到j需要买的最小票数,求p(i,j)之和
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <map> #include <bitset> #include <queue> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; #define LL long long #define ULL unsigned long long #define eps 1e-9 #define N (200000 + 10) #define M (50000 + 10) #define pii pair<int,int> #define MP make_pair #define inf 0x3f3f3f3f #define md (ll+rr>>1) #define lson ll, md, ls #define rson md + 1, rr, rs #define ls i<<1 #define rs i<<1|1 #define mod 1000000007 #define Pi acos(-1.0) int a[N]; LL ans; LL dp[N]; LL mi[N<<2]; int n; void update(int x, LL v, int ll, int rr, int i) { if(ll == rr) { mi[i] = v; return; } if(x <= md) update(x, v, lson); else update(x, v, rson); mi[i] = min(mi[ls], mi[rs]); } LL query(int l, int r, int ll, int rr, int i) { if(l == ll && r == rr) { return mi[i]; } if(r <= md) return query(l, r, lson); else if(l > md) return query(l, r, rson); else return min(query(l, md, lson), query(md+1, r, rson)); } void gao() { update(n, n, 1, n, 1); for(int i = n-1; i >= 1; --i) { LL k = query(i+1, a[i], 1, n, 1); dp[i] = k - a[i] + n - i; update(i, dp[i]+i, 1, n, 1); ans += dp[i]; } } int main() { scanf("%d", &n); int x; for(int i = 1; i < n; ++i) { scanf("%d", &x); a[i] = x; } ans = 0; gao(); printf("%I64d\n", ans); }