ARC 202 C Rotate and Play Game

ARC 202 C Rotate and Play Game

链接: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;
}
posted @ 2022-04-10 15:20  夜空之星  阅读(58)  评论(0编辑  收藏  举报