At338 D - Island Tour

D.Island Tour


原题链接

题意概述

给定一个长度为n的(\(n\geq 3\))序列,\(a_i与a_{i+1}之间连一条边(i < n)\),\(a_n与a_1之间连一条边\),每条边的长度是1,现给定长为m的点集合序列b,求可以任意删除一条边的情况下按照b的移动顺序经过的总路程S。

解题思路

注意到,序列有以下几个性质
1.没有删除边前,序列元素形成一个环。
2.没有删除边前,每次从\(b_i 到 b_{i+1}\)有两种代价的方式,
一种是直接从小边走向大边,消耗\(s1=|b_i-b_{i+1}|\)的代价,
另一种是小边绕一圈,消耗\(s2=|n-(b_i-b_{i+1})|\)的代价。
3.删除边后,每个点走向另一个点只有一种方案,相当于每次走边在没有删边的基础上多消耗了\(|s1-s2|\)的代价。
4.那么我们要解决的问题就转化到了\(总代价=删边前总代价和+加上删边后多的代价之和\)
删边前的总代价直接对两种走边方式取最大值即可,删边后多走的代价可以使用差分数组和前缀和还原的思想统计

AC code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll inf=1e18;
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,m;cin>>n>>m;
    vector<int>a(m+1);
    vector<ll>d(n+2);
    ll ans=0;
    for(int i=1;i<=m;i++) cin>>a[i];
    for(int i=1;i<m;i++){
        int u=a[i],v=a[i+1];
        if(u>v) swap(u,v);
        ll rt1=v-u,rt2=n-rt1;
        if(rt1<rt2){
            d[u]+=rt2-rt1,
            d[v]-=rt2-rt1;
        }
        else{
            d[v]+=rt1-rt2;
            d[u]-=rt1-rt2;
            d[1]+=rt1-rt2;
        }
        ans+=min(rt1,rt2);
    }
    for(int i=1;i<=n;i++) d[i]+=d[i-1];
    cout<<ans+*min_element(d.begin()+1,d.begin()+1+n)<<endl;
    return 0;
}
posted @ 2025-05-18 21:15  usedchang  阅读(28)  评论(0)    收藏  举报