codeforces 1343D(差分+思维)

 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 );

    }
}

猜你喜欢

转载自www.cnblogs.com/jrfr/p/12926813.html