Minimum Inversion Number
求最小反转数,就是求最少的逆序对。
逆序对怎么求,就是先把所有的数都初始化为0,然后按照顺序放入数字,放入数字前查询从这个数往后面的数的位置是不是被占了,被占了说明有逆序对。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define debug(n) printf("%d ",n) #define inf 0x3f3f3f3f; using namespace std; const int maxn = 5000 + 10; int n, a[maxn]; struct node { int l, r, num; }tree[4*maxn]; void push_up(int id) { tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num; } void build(int id, int l, int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].num = 0; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); push_up(id); } int query(int x, int y, int id) { int l = tree[id].l; int r = tree[id].r; if (x <= l && y >= r) { return tree[id].num; } int mid = (l + r) >> 1; int ans = 0; if (x <= mid) ans += query(x, y, id << 1); if (y > mid) ans += query(x, y, id << 1 | 1); push_up(id); return ans; } void update(int x, int y, int id) { int l = tree[id].l; int r = tree[id].r; if (x <= l && y >= r) { tree[id].num = 1; return; } int mid = (l + r) >> 1; if (x <= mid) update(x, y, id << 1); if (y > mid) update(x, y, id << 1 | 1); push_up(id); } int main() { while (scanf("%d", &n) != EOF) { int sum = 0,ans=inf; build(1, 0, n - 1); for (int i = 0;i < n;i++) { scanf("%d", &a[i]); sum += query(a[i], n - 1, 1); update(a[i], a[i], 1); //debug(sum); } //debug(sum); for (int i = 0;i < n;i++) { sum = sum + (n - 1 - a[i]) - a[i]; ans = min(sum, ans); } printf("%d ", ans); } return 0; }
对其中一个进行排序,转化成逆序对。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <algorithm> #include <string> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 2e5 + 10; typedef long long ll; map<ll, ll>mp; struct node { int l, r; int sum; }tree[4*maxn]; pair<ll, ll>a[maxn]; bool cmp(pair<ll,ll>a,pair<ll,ll>b) { return a.first > b.first; } bool cmp1(pair<ll,ll>a,pair<ll,ll>b) { return a.second < b.second; } void build(int id, int l, int r) { tree[id].l = l; tree[id].r = r; if (l == r) { tree[id].sum = 0; return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); } int query(int id,int x,int y) { int l = tree[id].l; int r = tree[id].r; if(x<=l&&y>=r) { // printf("id=%d sum=%d ", id,tree[id].sum); return tree[id].sum; } int ans = 0; int mid = (l + r) >> 1; if (x <= mid) ans += query(id << 1, x, y); if (y > mid) ans += query(id << 1 | 1, x, y); // printf("id=%d ans=%d l=%d r=%d x=%d y=%d ", id, ans, l, r,x,y); return ans; } void push_up(int id) { tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum; } void update(int id,int x) { int l = tree[id].l; int r = tree[id].r; if(l==r) { tree[id].sum = 1; return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, x); else update(id << 1 | 1, x); push_up(id); } int main() { int n, tot = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld%lld", &a[i].first, &a[i].second); sort(a + 1, a + 1 + n, cmp1); for(int i=1;i<=n;i++) { if (mp[a[i].second]) continue; mp[a[i].second] = ++tot; } sort(a + 1, a + 1 + n, cmp); build(1, 1, tot); int ans = 0; for(int i=1;i<=n;i++) { if (query(1, mp[a[i].second], tot)) ans++; update(1, mp[a[i].second]); } printf("%d ", ans); return 0; } /* 6 100 100 90 100 90 100 80 90 80 90 70 100 */
还有一个是选拔赛的题目,学校oj崩了,下次再写。