Codeforces Round #353 (Div. 2)E. Trains and Statistic(ST表+贪心)

来源:互联网 发布:网络录音电话 编辑:程序博客网 时间:2024/05/22 16:44

题意:有n个车站,每个车站有一个可达区间[i+1,ai],问所有车站的最小换站距离之和。
分析:设i为起点,k为[i+1,a[i]]中a[k]最大的车站编号,则对于任意j>ai,选择从k换站一定是最好的。

#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-9#define maxn 1000100#define MOD 1000000007int n,a[maxn];int st[maxn][30];long long dp[maxn];void init(){    for(int j = 1; j < 20; j++)        for(int i = 1; i+(1<<j)-1 < n; i++)            st[i][j] = a[st[i][j-1]]>a[st[i+(1<<(j-1))][j-1]]?st[i][j-1]:st[i+(1<<(j-1))][j-1];}int solve(int x,int y){    int len = log2(y-x+1);    return a[st[x][len]] > a[st[y-(1<<len)+1][len]]?st[x][len]:st[y-(1<<len)+1][len];}int main(){    int t;    while(scanf("%d",&n) != EOF)    {        for(int i = 1; i < n; i++)        {            scanf("%d",&a[i]);            st[i][0] = i;        }        init();        long long ans = 0;        dp[n] = 0;        for(int i = n-1; i > 0; i--)        {            if(a[i] == n)                dp[i] = (long long)(n-i);            else            {                int k = solve(i+1,a[i]);                dp[i] = dp[k] + (1ll)*(k - i + n - a[i]);            }            ans += dp[i];        }        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击