题目大意
每次给一个数加一或减一,问最小操作次数使一半是完全平方数一半不是。
题解
显然只需要将多的一部分变成少的一部分,贪心选需要操作次数最少的。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
char ch=getchar();int f=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') {f=f*10+(ch^48);ch=getchar();}
return f;
}
struct data
{
int num;
int step;
int type;
}a[500005];
bool cmp(data x,data y)
{
if(x.type==y.type)
{
return x.step<y.step;
}
else return x.type<y.type;
}
int n;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i].num=read();
int temp=sqrt(a[i].num);
if(temp*temp==a[i].num)
{
a[i].type=0;
if(a[i].num==0) a[i].step=2;
else a[i].step=1;
}
else
{
a[i].type=1;
a[i].step=min(a[i].num-temp*temp,(temp+1)*(temp+1)-a[i].num);
}
}
int pla=0;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
if(a[i].type==1)
{
pla=i-1;
break;
}
}
if(a[n].type==0) pla=n;
int pla2=n-pla;
//cout<<pla<<" "<<pla2<<endl;
if(pla>pla2)
{
long long ans=0;
for(int i=1;i<=n;i++)
{
ans+=a[i].step;
pla--;pla2++;
if(pla==pla2) break;
}
cout<<ans;
}
else if(pla<pla2)
{
long long ans=0;
for(int i=pla+1;i<=n;i++)
{
ans+=a[i].step;
pla++;pla2--;
if(pla==pla2) break;
}
cout<<ans;
}
else cout<<"0";
}