题目链接
题意:
给一个n大小的数组,n一定为偶数(且这个数组中的数字大大于于1小于等于k)。第i个位置和第n-i+1个位置为一对。现在要求每一对的和都要相等,问最少改变几次数组中的数。使得满足条件。
思路:
先按着贪心的思路去想,发现并不满足贪心的条件。
然后我们想,既然贪心不满足,也没有什么规律(即这个和相等的数是没有办法一步到位的),那么肯定是要做什么预处理。然后我们想,既然给定了一个数字的范围。那岂不是俩个数的和也是在一个范围内的。我们现在已经知道俩个数字,那么我们可以枚举和的范围,在俩数和一定时,这俩个数需要改变几次。再利用一下前缀和废话不多说,基本思路知道了,直接上代码比陈述管用。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[200005];//存储数字
int sum[400005];//前缀和数组
void add(int l,int r,int x)
{
if(l>r)return ;
sum[l]+=x;//在l到r内的和需要改变x次;
sum[r+1]-=x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<=2*k;i++)sum[i]=0;//初始化
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n/2;i++)
{
int aa=a[i],bb=a[n-i+1];//取一对
add(2,min(aa,bb),2);//和为2到aa,bb最小值的需要改变俩次数字,自己想想。。以下同理
add(min(aa,bb)+1,aa+bb-1,1);
add(aa+bb+1,max(aa,bb)+k,1);
add(max(aa,bb)+k+1,2*k,2);
}
for(int i=1;i<=2*k;i++)sum[i]=sum[i]+sum[i-1];//前缀和
int minn=1e9;
for(int i=2;i<=2*k;i++)minn=min(minn,sum[i]);//取和为i时,最小次数;
printf("%d\n",minn);
}
}