1. 程式人生 > >ARC 077 E guruguru - 差分

ARC 077 E guruguru - 差分

題目大意:走n-1步每次從a_i走到a_{i+1},每次位置+1(迴圈意義下)或者位置=x。求最小的x使得步數之和最小。1e5。
題解:顯然直接維護a[i]為x取i時能夠節省的答案,相當於是等差數列加法,差分差分然後字首和字首和即可。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db double
#define pb push_back #define mp make_pair #define fir first #define sec second #define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() { int x,
ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; } const int N=100010;lint a[N],b[N],c[N];int p[N]; inline int upd(int s,int t,int v) { int L=t-s;return c[s]+=v,c[s+1]+=1-v,c[t+1]-=v+L+1,c[t+2]+=v+L,0; } int main
() { // freopen("data.in","r",stdin); int m=inn(),n=inn();lint tot=0,ans=0;rep(i,1,m) p[i]=inn(); rep(i,1,m-1) { int s=p[i],t=p[i+1];if(s==t) continue; if(t==s+1||(s==n&&t==1)) { tot++;continue; } if(s<t) upd(s+1,t,0),tot+=t-s; else (s<n?upd(s+1,n,0):0),upd(1,t,n-s),tot+=t+n-s; } rep(i,1,n) b[i]=b[i-1]+c[i],a[i]=a[i-1]+b[i]; rep(i,1,n) ans=max(ans,a[i]); return !printf("%lld\n",tot-ans); }