//codeforces820d 递推+线段树
/*
每次将序列向左平移至下一个序列时,只用考虑当前序列里abs(p[i]-i)大于零的个数以及小于等于零的个数,
新的序列值等于(negative-positive)+abs(v[n-k+1]-1)-abs(v[n-k+1]-n),
因为abs(p[i]-i)>0时,整体左移时它的值会减1,而abs(p[i]-i)<=0时移动后值会加1,
其中v[n-k+1]是上一个序列末尾的元素,这次被移到了第一个,特殊考虑。
打表预处理每个序列中正数的个数。枚举所有元素,对于v[i],考虑以i开始向左数v[i]-1个位置(小于1了就到n再继续向左数),
如果以这些位置为起点,那么abs(p[i]-i)必然为正。用线段树维护,对这个区间内整体加1。
时间复杂度O(nlogn)
(最终踩着2sAC。。官方题解中给出了O(n)的dp,也是这个思想,但简化了太多。。
http://codeforces.com/blog/entry/52946
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
const int MAXN=1000005;
int stn[MAXN*4];
int laz[MAXN*4];
int v[MAXN];
int n;
void push_down(int now,int l,int r){
	int mid=(l+r)/2;
	laz[now<<1]+=laz[now];laz[(now<<1)+1]+=laz[now];
	stn[now<<1]+=(mid-l)*laz[now];stn[(now<<1)+1]+=(r-mid)*laz[now];
	laz[now]=0;
}
void push_up(int now){
	stn[now]=stn[now<<1]+stn[(now<<1)+1];
}
void update(int now,int l,int r,int tl,int tr,int t){
	if(tl<=l&&tr>=r){
		laz[now]+=t;
		stn[now]+=(r-l)*t;
		return;
	}
	push_down(now,l,r);
	int mid=(l+r)/2;
	if(tl<mid)
		update(now<<1,l,mid,tl,tr,t);
	if(tr>mid)
		update((now<<1)+1,mid,r,tl,tr,t);
	push_up(now);
}
int find(int now,int l,int r,int tl,int tr){
	if(tl<=l&&tr>=r)
		return stn[now];
	push_down(now,l,r);
	int mid=(l+r)/2,ans=0;
	if(tl<mid)
		ans+=find(now<<1,l,mid,tl,tr);
	if(tr>mid)
		ans+=find((now<<1)+1,mid,r,tl,tr);
	return ans;
}
int main(){
	scfd(&n);
	fr(i,1,n)
		scfd(&v[i]);
	fr(i,1,n){
		if(v[i]<2)continue;
		if(i-(v[i]-1)+1>=1)
			update(1,1,MAXN,i-(v[i]-1)+1,i+1,1);
		else{
			update(1,1,MAXN,1,i+1,1);
			update(1,1,MAXN,n-(v[i]-1-i)+1,n+1,1);
		}
	}
	ll ans=0,tans;
	int k=0,st=1,t=0;
	fr(i,1,n)
		ans+=(ll)abs(v[i]-i);
	tans=ans;
	while(1){
		k++;
		if(k>n-1)break;
		int ps=find(1,1,MAXN,st,st+1);
		int ng=n-ps-1;
		tans+=(ll)((ng-ps)+abs(v[n-k+1]-1)-abs(v[n-k+1]-n));
		if(tans<ans){
			ans=tans;
			t=k;
		}
		st=n-k+1;
	}
	printf("%lld %d\n",ans,t);
	return 0;
}
 posted on 2017-09-22 17:17  cylcy  阅读(84)  评论(0编辑  收藏  举报