zoukankan      html  css  js  c++  java
  • 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
    " , res);
    65     return 0;
    66 }
  • 相关阅读:
    .NET/C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
    使用UI Automation实现自动化测试--1-4
    使用npm命令下载sass时出现Error: not found: python2
    CentOS上安装Python3
    解决electron打包时,下载超时导致失败
    FJ省队集训2021
    微信小程序自定义封装组件-showModal
    react性能优化
    认识react虚拟Dom
    前端FileReader读取文件信息
  • 原文地址:https://www.cnblogs.com/Recoder/p/5605233.html
Copyright © 2011-2022 走看看