Codeforces Round #636 (Div. 3) D.Constant Palindrome Sum
题目链接
You are given an array a consisting of n integers (it is guaranteed that n is even, i.e. divisible by 2). All ai does not exceed some integer k.
Your task is to replace the minimum number of elements (replacement is the following operation: choose some index i from 1 to n and replace ai with some integer in range [1;k]) to satisfy the following conditions:
after all replacements, all ai are positive integers not greater than k;
for all i from 1 to n2 the following equation is true: ai+an−i+1=x, where x should be the same for all n2 pairs of elements.
You have to answer t independent test cases.
Input
The first line of the input contains one integer t (1≤t≤1e4) — the number of test cases. Then t test cases follow.
The first line of the test case contains two integers n and k (2≤n≤2e5,1≤k≤2e5) — the length of a and the maximum possible value of some ai correspondingly. It is guratanteed that n is even (i.e. divisible by 2). The second line of the test case contains n integers a1,a2,…,an (1≤ai≤k), where ai is the i-th element of a.
It is guaranteed that the sum of n (as well as the sum of k) over all test cases does not exceed 2⋅105 (∑n≤2e5, ∑k≤2e5).
Output
For each test case, print the answer — the minimum number of elements you have to replace in a to satisfy the conditions from the problem statement.
Example
input
4
4 2
1 2 1 2
4 3
1 2 2 1
8 7
6 1 1 7 6 3 4 6
6 6
5 2 6 1 3 4
output
0
1
4
2
比较巧妙的一道题目~
我们任意想到暴力,即从
里面一个个枚举,找最少替代次数,这样想肯定是会超时的,所以我们考虑用预处理的方式快速计算每个数需要的最少替代次数
首先用
记录每一对
出现的次数
然后用
记录每一对
变换一次得到的数的范围,很容易发现这个范围就是
,通过记录端点的值控制区间修改,即
,
,那么对每个数
,所需的最小变换次数就是
,遍历更新一下答案即可,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
vector<int>a(n);
for(auto &i:a) cin>>i;
vector<int>cnt(2*k+1);
for(int i=0;i<n/2;i++)
cnt[a[i]+a[n-i-1]]++;
vector<int>pre(2*k+2);
for(int i=0;i<n/2;i++){
int l1=a[i]+1,r1=a[i]+k;
int l2=a[n-i-1]+1,r2=a[n-i-1]+k;
pre[min(l1,l2)]++;
pre[max(r1,r2)+1]--;
}
for(int i=1;i<=2*k+1;i++) pre[i]+=pre[i-1];
int ans=1e9;
for(int i=2;i<=2*k;i++){
ans=min(ans,(pre[i]-cnt[i])+(n/2-pre[i])*2);
}
cout<<ans<<endl;
}
return 0;
}