2 条题解
-
0
题意分析
- 问题本质:计算将序列通过相邻交换排序所需的最少操作次数
- 关键观察:该问题等价于计算序列的逆序数(inversion count)
- 逆序数定义:对于序列中所有元素对,当且时,称为一个逆序对
- 结论:最少交换次数 = 序列的逆序数
解题思路
-
直接计算(暴力法):
- 双重循环统计所有逆序对
- 时间复杂度,对不可行
-
高效算法:
- 归并排序法:在归并过程中统计逆序数,时间复杂度
- 树状数组/线段树:离散化后统计,时间复杂度
实现步骤(归并排序法)
-
输入处理:
- 读取序列长度
- 读取个整数存入数组
-
归并排序:
- 递归分割数组
- 合并有序子数组时:
- 当右子数组元素小于左子数组元素时,累加逆序数(增加量为左子数组剩余元素数)
-
输出结果:
- 返回累计的逆序数
代码实现
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <vector> #include <cmath> #define endl "\n" #define LL long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define debug(x); cout<<x<<endl; #define lowbit(x) ((x)&(-x)) using namespace std; /*** * Author Informathons : * @author: 六月陌 ***/ const int maxn=5e5+10; const int mod=1e9+7; struct node { int num; //存数字 int id; //存初始位置 }a[maxn]; int c[maxn]; // 树状数组 int Index[maxn]; // 存排序后的位置(相当于离散化) int n; LL ans = 0; //最终结果 bool cmp(node x,node y) { return x.num < y.num; } void update(int x,int k) //更新树状数组,在位置x加k { while(x<=n) { c[x] += k; x += lowbit(x); } } int getsum(int x) //查询从头到x的总和,也就是1的个数 { int res = 0; while(x>0) { res += c[x]; x -= lowbit(x); } return res; } int main() { while(scanf("%d",&n)!=EOF) { if(n == 0) break; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { scanf("%d",&a[i].num); a[i].id = i; } sort(a+1,a+n+1,cmp); // 快排排个序就有了最终位置 //↓↓↓ 记录每个元素的初始位置对应的最终位置 ↓↓↓ Index[a[1].id] = 1; for(int i=2;i<=n;i++) { if(a[i].num == a[i-1].num) Index[a[i].id] == Index[a[i-1].id]; else Index[a[i].id] = i; } ans = 0; for(int i=1;i<=n;i++) { ans += i - 1 - getsum(Index[i]); // 放第i个元素的时候有i-1个,且getsum(Index[i])个元素不用移动 所以就有 i - 1 - getsum(Index[i])个需要移动 update(Index[i],1); } printf("%lld\n",ans); } return 0; }
-
0
逆序对板子题,不过会卡时间
int nw[N], tr[N]; PII w[N]; int lowbit(int x){ return x & -x; } void ADD(int x, int c){ for(int i = x; i <= n; i += lowbit(i)) tr[i] += c; } int SUM(int x){ ll res = 0; for(int i = x; i; i -= lowbit(i)) res += tr[i]; return res; } void solve() { while(cin >> n, n){ idx = 0; for(int i = 1; i <= n; i ++) tr[i] = 0; for(int i = 1; i <= n; i ++){ cin >> w[i].x; w[i].y = i; } sort(w + 1, w + n + 1); ll sum = 0; for(int i = 1; i <= n; i ++){ int id = w[i].y; sum += i - SUM(id) - 1; ADD(id, 1); } cout << sum << endl; } }
- 1
信息
- ID
- 1300
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 7
- 已通过
- 2
- 上传者