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; }