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

Posted ccsu-kid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",ans);
}
/*
7
3 1 4 1 5 9 2
*/

 

 

以上是关于Asia Yokohama Regional Contest 2018 G题 What Goes Up Must Come Down(树状数组求逆序对)的主要内容,如果未能解决你的问题,请参考以下文章

Asia Yokohama Regional Contest 2018 B题 - Arithmetic Progressions(dp)

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

2019 ICPC Asia Yinchuan Regional

2018 ICPC Asia Jakarta Regional Contest

2019 ICPC Asia Nanjing Regional

2014 ACM/ICPC Asia Regional 北京 Online