• Asia Yokohama Regional Contest 2018 G题 What Goes Up Must Come Down(树状数组求逆序对)


    https://codeforces.com/gym/102082

    题意:

      给一个数组大小不超过1e5,每个数的值也是1e5以内,可以交换相邻两个数,求保证它呈现一个非递减再非递增的趋势的最小交换次数。

     
    题解:
      对每个数来说,只有两种情况,要么参与非递减部分要么参与非递增部分,对于前者它要移的次数就是在它之前与他构成的逆序对数,对于后者它要移的次数就是在它之后与他构成的逆序对数,那我们取较小的加入到答案就做完了。
    #define bug(x,y) cout<<"i="<<x<<": "<<y<<endl
    #define IO std::ios::sync_with_stdio(0);
    #include <bits/stdc++.h>
    #define itor ::iterator
    using namespace  std;
    typedef long long ll;
    typedef pair<ll,ll>P;
    #define pb push_back
    #define se second
    #define fi first
    #define rs o*2+1
    #define ls o*2
    const int N=1e5+5;
    int n;
    int c[N];
    int low(int x){
        return x&(-x);
    }
    void add(int x,int y){
        while(x<N){   
            c[x]+=y;
            x+=low(x);
        }
    }
    int cal(int x){
        int res=0;
        while(x){
            res+=c[x];
            x-=low(x);
        }
        return res;
    }
    vector<int>v[N];
    int main(){
        scanf("%d",&n);
        ll ans=0;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            v[x].pb(i);
            add(i,1);
        }
        for(int i=1;i<N;i++){
            if(v[i].empty())continue;
            for(int j=0;j<v[i].size();j++){
                int x=v[i][j];
                add(x,-1);
                n--;
            }
            for(int j=0;j<v[i].size();j++){  
                int x=v[i][j];
                ll res=min(cal(x-1),n-cal(x));
                //bug(i,res);
                ans+=res;
            }
        }
        printf("%lld
    ",ans);
    }
    /*
    7
    3 1 4 1 5 9 2
    */
     
  • 相关阅读:
    JavaScript寄生组合式继承分析
    常用的css命名规则:
    jshint配置(js检查)
    当页面关闭或刷新时提示用户
    Ionic 开发环境搭建
    VS Code前端开发利器-常用快捷键
    Uploadify 上传插件引起Chrome崩溃解决方法
    “全栈工程师”的尴尬
    redis集群升级,数据迁移及校验
    K-means
  • 原文地址:https://www.cnblogs.com/ccsu-kid/p/10599346.html
Copyright © 2020-2023  润新知