D. Mister B and PR Shifts

 

 

const int N = 2e6 + 5;//开两倍空间

int n;
arr p,cnt;
int l,r,m;
ll sum = 0,ans;

int main()
{
    // file("test");
    sdf(n);
    For(i, 1, n) sdf(p[i]);
    For(i, 1, n)
    {
        sum += abs(p[i] - i);
        if (p[i] >= i)//起始默认中立派暂属于左翼
            l++,cnt[0+p[i]-i]++; //左翼,第(0+p[i]-i)轮的中立者个数+1
        else if (p[i] < i)
            r++;
    }
    int id = 0;
    ans = sum;
    For(i, 1, n)
    {
        r += cnt[i - 1], l -= cnt[i - 1];//将上一轮的中立者从左翼变为右翼
        sum = sum + (r - l) - 1;//r代表有r个人一定向右移动了一格,对sum的贡献就是r,l同理。但是最后一个点要单独处理,不能参与这里的贡献
        sum = sum - (n - p[n - i + 1]) + (p[n - i + 1] - 1); //减掉最后一个点贡献,转移到加上第一个点贡献
        r--;//不用担心最后一位是中立派的问题,因为反正到了那个时候,cnt[i-1]自然会处理的
        l++;
        cnt[i+p[n - i + 1] - 1]++;//第i轮后的p[n-i+1]-1轮的中立者个数+1
        if (sum <ans)
        {
            ans = sum;
            id = i;
        }
    }
    cout << ans << " " << id;

    return 0;
}

 

posted @ 2018-08-06 02:44  planche  阅读(185)  评论(0编辑  收藏  举报