题面在这里
最终状态一定是一个先增后减的峰形
然后交换次数其实等于 最终状态的\(id\)序列的逆序对数
考虑按高度从小到大加入最终的序列,只能放在两端,分别统计答案,选小的那个
用树状数组维护 未加入的点的\(id\)分布情况
示例程序:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | #include<cstdio>#include<algorithm>
 using namespace std;
 typedef long long ll;
 
 const int maxn=300005;
 int n;
 struct data{
 int x,id;
 bool operator<(const data&b)const {return x<b.x;}
 }a[maxn];
 int b1[maxn],b2[maxn];
 #define lowbit(x) ((x)&-(x))
 void ist(int x,int w){
 for (int i=x;i<=n;i+=lowbit(i)) b1[i]+=w;
 for (int i=x;i>=1;i-=lowbit(i)) b2[i]+=w;
 }
 int qry(int x){
 int r1=0,r2=0;
 for (int i=x;i>=1;i-=lowbit(i)) r1+=b1[i];
 for (int i=x;i<=n;i+=lowbit(i)) r2+=b2[i];
 return min(r1,r2);
 }
 int main(){
 scanf("%d",&n);
 for (int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].id=i,ist(i,1);
 sort(a+1,a+1+n);
 ll ans=0;
 for (int i=1,j=1;i<=n;i=j){
 for (j=i;j<=n&&a[i].x==a[j].x;j++) ist(a[j].id,-1);
 for (j=i;j<=n&&a[i].x==a[j].x;j++) ans+=qry(a[j].id);
 }
 printf("%lld",ans);
 return 0;
 }
 
 |