ARC 202 C Rotate and Play Game
ARC 202 C Rotate and Play Game
好题。
这题有一个结论是:通过若干次操作,前 \(\dfrac{n}{2}\) 大的数一定能被取到。
下面我们来证明它:
对于一开始给定数组 \(A\),如果满足 \(A_i\) 的值是前 \(\dfrac{n}{2}\) 大的,那么将 \(B_i\) 设为 \(-1\)。否则将 \(B_i\) 设为 \(1\)。
那么我们能取到所有前 \(\dfrac{n}{2}\) 大的值的条件是 \(B\) 数组的任意一个前缀和大于等于 \(0\)。
这个通过数学归纳法易得。
那么我们只要找到一个 \(k\),使得将 \(B\) 左移 \(k\) 次后其任意前缀和大于等于 \(0\) 即可。
我们设 \(C_i=C_{i-1}+B_i\)。找到一个最小的 \(C_x\) 满足 \(\forall i\in[1,n],C_x\le C_i\)。
那么 \(k=x\) 时,\(B\) 的任意前缀和大于等于 \(0\)。
这个也可以证明:
易知左移后的数组为 \(B_{x+1}\dots B_n,B_1\dots B_k\)。
由于原数列中 \(+1,-1\)的个数相同,所以 \(C_n=0\) 。那么 \(C_x\le 0\)。
又 \(\forall i\in[x+1,n],C_i-C_x\ge 0\)。所以 \(B_x+1\dots B_n\) 这一段的任意前缀和大于等于 \(0\)。
因为 \(C_n=0\) 。所以 \(C_n-C_x=-C_x\)。
那么 \(\forall i\in[1,x]\) \(C_i+(C_n-C_x)\ge 0\)。
也就是 \(B_1,\dots B_k\) 这一段任意前缀和大于 \(0\)。
得证。
模拟上述过程即可。使用排序来找前 \(\dfrac{n}{2}\) 大的数,复杂度 \(O(n\log n)\)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2e5+5;
ll Ans;
int n,A[MAXN],B[MAXN],idx[MAXN];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&A[i]);
for(int i=1;i<=n;++i) idx[i]=i;
sort(idx+1,idx+1+n,[&](int x,int y){return A[x]<A[y];});
for(int i=1;i<=n/2;++i) A[idx[i]]=1;
for(int i=n/2+1;i<=n;++i) Ans+=A[idx[i]],A[idx[i]]=-1;
int p=n;
for(int i=1;i<n;++i)
{
A[i]+=A[i-1];
if(A[p]>A[i]) p=i;
}
printf("%d %lld\n",p==n?0:p,Ans);
return 0;
}