can
题意:t个样例。给长度为n的数组a和k,n为偶数。a数组每个值都小于k。你可以改变数组的任意一个数到范围【1,k】,使得数组a满足对任意i,a[i]+a[n-i+1]相等。输出改变数组中的数的最小个数。
思路:n和k一共不超过2e5。如果一对数都更改,则范围都为【2,2*k】。如果一对数(x和y,x>y)只更改范围,则范围为【1 + y,x+k】。如果一对数都不更改,则..........。
可以记录下来一个数都不更改vis的和只更改了一个数的vis2。遍历2到2*k,当所有对数为i时,最小解为 vis2[i] + ((n/2)-vis2[i])*2 - vis[i]。更改vis2会超时,用差分把区间转化为两个端点即可。
#include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <string> #include <map> #include <iomanip> #include <algorithm> #include <queue> #include <stack> #include <set> #include <vector> //const int maxn = 1e5+5; #define ll long long #define inf 0x3f3f3f3f #define FOR(i,a,b) for( int i = a;i <= b;++i) #define bug cout<<"--------------"<<endl #define P pair<int, int> #define fi first #define se second ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} using namespace std; const int maxn = 2e5+10; int n,k; int a[maxn*2],vis[maxn*2],vis2[maxn*2],cf[maxn*2]; int solve() { for(int i = 2;i <= 2*k; ++i) { if(vis[i] == n/2) { return i; } } return 0; } int solve2() { ll ans = n+10; ll cnt = 0; for(int i = 2;i <= 2*k; ++i) { cnt += cf[i]; ll nub = cnt+ ((n/2)-cnt)*2 - vis[i]; ans = min(ans,nub); } return ans; } void clear() { for(int i = 2;i <= 2*k; ++i) { cf[i] = 0; vis[i] = 0; } } int main() { //freopen("input.txt", "r", stdin); int q; scanf("%d",&q); while(q--) { //cin>>n>>k; scanf("%d %d",&n,&k); clear(); for(int i = 1;i <= n; ++i) { //cin>>a[i]; scanf("%d",&a[i]); } for(int i = 1;i <= n/2; ++i) { int tmp = a[i]+a[n-i+1]; vis[tmp]++; } int ans = solve(); if(ans == n/2) { //cout<<0<<endl; printf("0\n"); continue; } for(int i = 1;i <= n/2; ++i) { int x = a[i]; int y = a[n-i+1]; if(x <= y) { int temp = x; x = y; y = temp; } int l = 1 + y; int r = x + k; cf[l]++; cf[r+1]--; /*for(int j = l;j <= r; ++j) vis2[j]++;*/ } ans = solve2(); /* for(int i = 2;i <= 2*k; ++i) { cout<<vis[i]<<" "; } cout<<endl; for(int i = 2;i <= 2*k; ++i) { cout<<vis2[i]<<" "; } cout<<endl; for(int i = 2;i <= 2*k; ++i) { ll nub = vis2[i] + ((n/2)-vis2[i])*2 - vis[i]; cout<<nub<<" "; } cout<<endl;*/ //cout<<ans<<endl; printf("%d\n",ans ); } }