题解:AT_arc194_b [ARC194B] Minimum Cost Sort

一个显然的性质是,将最大的数向最右交换一定不劣。

在最大的数就绪之后,再处理次大数,依次下去直到处理完整个序列。

在逐级交换的过程中,会将较小数向继续左移,所以我们要统计一个数左边比它大的数,即逆序对。

我们设左边数的个数 \(k\),这个数初始位置 \(x\),以及需要交换到的 \(y\) 那么这个数在交换的过程中消耗的价值即为:

\[{\sum_{i=\min(x-k,y)}^{\max(x-k,y)}(i-1)} \]

就是从当前位置到部署位置成本的累加,化简下来则为:

\[{\dfrac{\left(x-k-1+y\right)×\left|x-k-y\right|}{2}} \]

最后再用树状数组求逆序对即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,m;
struct node{
        int num,tp;
        bool operator <(const node &a){
        	if(a.num!=num){
        		return a.num>num;
			}
			return a.tp>tp;
		}
}q[N];
int c[N];
vector<int> g[N];
inline int lb(int x){
        return x & (-x);
}
void add(int x){
        for(int i=x;i<=n;i+=lb(i)){
			c[i]+=1;
		}
}
int query(int x){
        int t=0;
        for(int i=x;i;i-=lb(i)){
        	t+=c[i];
		}
        return t;
}
int ans;
signed main(){
		ios::sync_with_stdio(false);
		cin.tie(0); cout.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>q[i].num;
        }
        for(int i=1;i<=n;i++){
                int s=query(n-q[i].num+1);
                ans+=((i-s)+(i-1))*((i-1)-(i-s)+1)/2;
                add(n-q[i].num+1);
        }
        cout<<ans<<endl;
}
posted @ 2025-05-20 08:12  Zom_j  阅读(18)  评论(0)    收藏  举报