zoukankan      html  css  js  c++  java
  • Tree Burning(前后缀和)

    题目链接:https://atcoder.jp/contests/agc030/tasks/agc030_b

    题意:

      在一个有 L 个单位长度的圆上有 n 个点, 小明位于 0 位置的人要按照步骤把 n 个点走完。

      圆的单位下标为[0, L-1],每个点有一个位置x[i] 。  

    步骤:

      1、如果所有的点都被走完,游戏结束。

      2、小明选择顺时针或者逆时针方向行走。

      3、小明按照步骤2 选定的方向行走,直到碰见第一个未走过的点, 继续执行步骤1 。

    输出:

      小明行走的最远距离。

    思路:

      已知小明若要行走的距离最远, 必然要左右横跳。

      对于到达结束过程的点 i 之前, 小明会在其左边经历 i - 1 个点, 在其右边经历 n - i 个点, 记二者较小值为 num, 则 num 为反复横跳数。

      若要行走距离尽可能大, 则要走到尽可能远的地方开始跳。 因此,我们只需要枚举从哪个点开始左右跳,并以此计算左右跳过程中行走的距离,以及最后一步是从左还是从右到达即可。

    代码:

      

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn=2e5+10;
     5 int L, n;
     6 ll pre[maxn], a[maxn], suf[maxn];
     7 ll solve() {
     8     ll res=a[n];
     9     for (int i=1; i<=n; ++i) pre[i] = pre[i-1]+a[i];
    10     for (int i=n; i>=1; --i) suf[i] = suf[i+1]+L-a[i];
    11     for (int i=1; i<=n; ++i) {
    12         int det = n-i, p = i+(det>>1);
    13         if(det&1)
    14             res = max(res, (suf[p+2]+pre[p]-pre[i-1])*2+L-a[p+1]);
    15         else
    16             res = max(res, (suf[p+1]+pre[p-1]-pre[i-1])*2+a[p]);
    17     }
    18     return res;
    19 }
    20  
    21 int main() {
    22     scanf("%d%d", &L,&n);
    23     for (int i=1; i<=n; ++i) scanf("%lld", a+i);
    24     ll ans = solve();
    25     reverse(a+1, a+1+n);
    26     for (int i=1; i<=n; ++i) a[i] = L-a[i];
    27     printf("%lld
    ", max(ans, solve()));
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    类型反射和晚期绑定
    JS读写Cookie(设置、读取、删除)
    数据绑定
    解读代码
    ASP.NET vNext (一)- 基本概念和环境配置
    设计模式总结
    面向接口编程技术架构图
    搞个这样的APP要多久? (转)
    网站服务架构(转)
    jexus
  • 原文地址:https://www.cnblogs.com/acerkoo/p/10506615.html
Copyright © 2011-2022 走看看