测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A25981. 最佳策略

填空题 较易

题目描述

最佳策略

题目描述

有n个小朋友排成一排,现在需要按身高从低到高的顺序进行排列。排序方式为:如果位置相邻的两个小朋友不符合从低到高的顺序,就交换这两个小朋友的位置。且每个小朋友都有一个不高兴的数值,开始的时候,所有小朋友的不高兴值为0。如果某个小朋友第一次被交换,则他的不高兴值加1,如果第二次被交换,则他的不高兴值加2,如果第三次被交换,则他的不高兴值加3,依此类推。

假如:一个小朋友被交换了3次,他的不高兴值为6(1+2+3)。

如果让所有小朋友都按从低到高的顺序排好队,那么所有小朋友的不高兴值的总和的最小值是多少(也就是交换次数最少,不高兴值得总和最小)。

注意:

1.如果有两个小朋友身高一样,谁在谁前无所谓(不需要交换);

2.每次交换的两个小朋友都需要增加不高兴值。

输入描述

第一行输入一个正整数n(2<n<51)表示小朋友的数量。

第二行输入n个正整数(每个正整数<160),分别表示n个小朋友的身高,正整数之间以一个空格隔开。

输出描述

输出所有小朋友的不高兴值的总和的最小值。

样例输入

3
130 115 98

样例输出

9

参考答案

#include <cstdio> #include <cstring> #include <iostream> #define maxn 100005 #define MAXN 1000005 using namespace std; int c[MAXN], a[MAXN]; long long b[maxn]; int n; // 获取最小比特 int lowbit(int x) { return x & (-x); } // 获取前x项和 int getSum(int x) { int s = 0; for (int i = x; i; i -= lowbit(i)) s += c[i]; return s; } // 修改更新 void add(int x, int val) { for (int i = x; i < MAXN; i += lowbit(i)) { c[i] += val; } } int main() { scanf("%d", &n); // 左边逆序对 memset(c, 0, sizeof(c)); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); add(a[i] + 1, 1); b[i] = (i + 1) - getSum(a[i] + 1); } // 右边逆序对 memset(c, 0, sizeof(c)); for (int i = n - 1; i >= 0; i--) { add(a[i] + 1, 1); b[i] += getSum(a[i]); } long long ans = 0; for (int i = 0; i < n; i++) { ans += (1 + b[i]) * b[i] / 2; } printf("%lld\n", ans); }
上一题 下一题