zoukankan      html  css  js  c++  java
  • 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
    ");
                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
    ",ans );
    
        }
    }
  • 相关阅读:
    回溯算法(DFS:深度优先)
    KNN原理和实现
    Anaconda虚拟环境控制
    c++容器
    最坏情况为线性时间的选择算法
    JVM原理解析
    substr、substring和slice的区别
    word-wrap与break-word属性的区别
    js修改伪类的值
    快速批量删除文件名中相同的文字
  • 原文地址:https://www.cnblogs.com/jrfr/p/12926813.html
Copyright © 2011-2022 走看看