ARC 077 E guruguru - 差分
阿新 • • 發佈:2018-11-01
題目大意:走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);
}