题解: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;
}

浙公网安备 33010602011771号