HDU-1394(线段树|归并排序)
来源:互联网 发布:三国无双Mac版 编辑:程序博客网 时间:2024/06/04 18:39
Minimum Inversion Number
题目意思是给你一个数组, 让你求数字对 (a[i],a[j]) 满足i
归并排序的思想
假设排序是从小到大的,当右边的A[j]复制到T中时, 左边的还没来得及复制到T中的那些数就是左边所有比A[j]大的数,因此,在累加器中加上左边元素个数即可。
求出第一个序列的逆序对之后可以递推推出其他序列的逆序对,取最大值,具体操作可以看代码
#include <cstdio>#include <cstring>using namespace std;const int N = 6000;int a[N], b[N], cnt, c[N];void MergeSort(int *A, int l, int r, int *T) {// printf("l == %d, r == %d\n", l, r); if(r - l > 1) { int m = l + (r - l)/2; int p = l, q = m, i = l; MergeSort(A,l,m,T); MergeSort(A,m,r,T); while(p < m || q < r) { if(q >= r || (p < m && A[p] <= A[q])) T[i++] = A[p++]; else T[i++] = A[q++], cnt += m - p; } for (i = l; i < r; i++) A[i] = T[i]; }}int main() { int n; while(scanf("%d", &n) != EOF) { cnt = 0; for (int i = 0; i < n; i++) { scanf("%d", a+i); c[i] = a[i]; } MergeSort(a,0,n,b); int mx = cnt;// printf("cnt == %d\n", cnt); for (int i = 0; i < n-1; i++) { cnt = cnt - c[i] + n - c[i] - 1; if(mx > cnt) mx = cnt; } printf("%d\n", mx); } return 0;}
以上代码中p属于[l,m),q属于[m,r)。p所在区间下标一定小于q所在区间下标。当A[p]>A[q],由于A[p]->A[m-1]是按照从小到大的顺序开始排的。所以,当最小的值都大于A[q]。所以区间[p,m)是满足逆序对的条件的.直接在最后方加上m-p即可。
线段树方法
先看代码
#include <iostream>#include <cstring>#include <algorithm>#define lson l, m, rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 5555;int SegTree[maxn << 2];void PushUP(int rt) { SegTree[rt] = SegTree[rt<<1] + SegTree[rt<<1|1];}void updata(int p, int l, int r, int rt) { if(l == r) { SegTree[rt]++; return ; } int m = (l + r) >> 1; if(p <= m) updata(p,lson); else updata(p,rson); PushUP(rt);}int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) return SegTree[rt]; int m = (l + r) >> 1; int ret = 0; if(L <= m) ret += query(L,R,lson); if(R > m) ret += query(L,R,rson); return ret;}int main() { int n; int sum[maxn]; while(cin >> n) {// build(0,n-1,1); memset(SegTree,0,sizeof(SegTree)); int ans = 0,ret = INF; for (int i = 0; i < n; i++) { cin >> sum[i]; ans += query(sum[i],n-1,0,n-1,1); updata(sum[i],0,n-1,1); } for (int i = 0; i < n-1; i++) { ans += n - sum[i] - sum[i] - 1; ret = min(ans,ret); } cout << ret << endl; } return 0;}
由于线段树是按照顺序更新的,后面更新线段树的下标一定比之前更新的下标是要大的,所以只要查看当前位置往后查看已经更新的数字数目就可以知道,逆序对的对数。
阅读全文
0 0
- HDU 1394 线段树 || 归并排序
- HDU-1394(线段树|归并排序)
- HDU 1394 Minimum Inversion Number【线段树&&归并排序】
- HDU 1394 Minimum Inversion Number( 归并排序 & 线段树 )
- [HDU 1394]Minimum Inversion Number(归并排序/线段树)
- HDU 1394 暴力 或 归并排序 或 线段树
- HDU 4911 Inversion【归并排序||线段树】
- hdu 1394 Minimum Inversion Number 逆序数 线段树&归并排序
- HDU 1394 Minimum Inversion Number【线段树,归并排序,树状数组】
- HDU 1394 Minimum Inversion Number(线段树/归并排序求逆序对数)
- HDU 1394 Minimum Inversion Number(求逆序对+线段树||归并排序)
- hdu 1394 Minimum Inversion Number(线段树)【归并排序模板】
- HDU-1394-Minimum Inversion Number(暴力||归并排序||线段树||树状数组)
- hdu 1394 归并排序
- hdu 5107 线段树+离散化+归并排序+极角排序
- [hdu]1394 Minimum Inversion Number -- 暴力求逆序、树状数组求逆序、线段树求逆序、归并排序求逆序
- hdu 1394 求循环串的最小逆序数 暴力法 线段树 归并排序3种方法
- HDU 1394 Minimum Inversion Number(循环数组求逆序数)(暴力,归并排序,线段树)
- Appium简介以及工作原理
- hdu 6052 To my boyfriend 暴力枚举+容斥去重
- STL学习之十五:STL综合案例--演讲比赛
- 题目1047:素数判定
- js获取当前时间的年月日时分秒
- HDU-1394(线段树|归并排序)
- HDU
- 修改Metasploit安卓Payload源码以实现持久化访问
- springMVC学习总结
- 判断Cpu的字节序
- JVM调优总结(一):概念
- STL总结——set
- 由结构体对齐而引发的思考(二)类对象内存模型
- ffmpeg之demux 解复用