您的位置:首页 > 大数据 > 人工智能

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

2016-10-03 19:39 351 查看
题意:有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 1000000007

int 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
= 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: