令
di
表示
i
次操作后的答案。
考虑
当
i≤pi
时:
- dj+=pi−i+j , j∈[0,pi−i]
- dj+=i−pi+j , j∈[pi−i+1,n−i]
- dj+=pi−i+n−j , j∈[n−i+1,n−1]
当 pi<i 时
- dj+=i−pi+j , j∈[0,n−i]
- dj+=pi−i+n−j , j∈[n−i+1,n+pi−i]
- dj+=i−pi−n+j , j∈[n−i+pi+1,n−1]
令
di=ki+b
,枚举
p
,更新
时间复杂度加了读优才过。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if(p1==p2){
p2=(p1=buf)+fread(buf,1,100000,stdin);
if(p1==p2)return EOF;
}
return *p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define N 1000010
#define ll long long
ll c[2][N<<2],p[2][N<<2],Tmp,Ans=1e18,d[N];
int i,j,k,n,m,x;
inline void Push(int x,int l){
int l1=l+1>>1,l2=l>>1;
if(p[0][x]){
if(l1==1)
c[0][x<<1]+=p[0][x];
p[0][x<<1]+=p[0][x];
if(l2==1)
c[0][x<<1|1]+=p[0][x];
p[0][x<<1|1]+=p[0][x];
p[0][x]=0;
}
if(p[1][x]){
if(l1==1)
c[1][x<<1]+=p[1][x];
p[1][x<<1]+=p[1][x];
if(l2==1)
c[1][x<<1|1]+=p[1][x];
p[1][x<<1|1]+=p[1][x];
p[1][x]=0;
}
}
inline void Update(int x,int l,int r,int L,int R,int y,bool d){
if(l>R||r<L)return;
if(l>=L&&r<=R){
if(l==r)c[d][x]+=y;
p[d][x]+=y;
return;
}
int Mid=l+r>>1;
Update(x<<1,l,Mid,L,R,y,d);
Update(x<<1|1,Mid+1,r,L,R,y,d);
}
inline void GetAns(int x,int l,int r){
if(l==r){
d[l]=c[0][x]+1ll*l*c[1][x];
return;
}
Push(x,r-l+1);
int Mid=l+r>>1;
GetAns(x<<1,l,Mid);
GetAns(x<<1|1,Mid+1,r);
}
inline void Add(int l,int r,int x,int y){
if(l>r)return;
Update(1,0,n-1,l,r,x,0);
Update(1,0,n-1,l,r,y,1);
}
int main(){
Read(n);
for(i=1;i<=n;i++){
Read(x);
if(x>=i)Add(0,x-i,x-i,-1),Add(x-i+1,n-i,i-x,1),Add(n-i+1,n-1,x-i+n,-1);else
Add(0,n-i,i-x,1),Add(n-i+1,n-i+x,x-i+n,-1),Add(n-i+x+1,n-1,i-x-n,1);
}
GetAns(1,0,n-1);
for(i=0;i<n;i++)if(d[i]<Ans)Ans=d[i],x=i;
printf("%I64d %d\n",Ans,x);
return 0;
}