HDU - 1394 - Minimum Inversion Number (线段树 - 单点更新,区间求和)

来源:互联网 发布:360数据流量控制 编辑:程序博客网 时间:2024/06/05 18:34


题目传送:Minimum Inversion Number


思路:线段树,求最小逆序数,先可以通过n*logn的时间用线段树求出初始的逆序对数,然后递推求出其他的解,递推过程看代码


AC代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <deque>#include <cctype>#define LL long long#define INF 0x7fffffffusing namespace std;const int maxn = 50005;int n;int sum[maxn << 2];int a[maxn];void build(int l, int r, int rt) {//初始建树 sum[rt] = 0;if(l == r) return;int mid = (l + r) >> 1;build(l, mid, rt << 1);build(mid + 1, r, rt << 1 | 1);}int query(int L, int R, int l, int r, int rt) {//区间查询 if(L <= l && r <= R) {return sum[rt];}int mid = (l + r) >> 1;int ret = 0;if(mid >= L) ret += query(L, R, l, mid, rt << 1);if(R >= mid + 1) ret += query(L, R, mid + 1, r, rt << 1 | 1);return ret;}void update(int p, int l, int r, int rt) {//更新 if(l == r) {sum[rt] ++;return;}int mid = (l + r) >> 1;if(p <= mid) update(p, l, mid, rt << 1);else update(p, mid + 1, r, rt << 1 | 1);sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; }int main() {while(scanf("%d", &n) != EOF) {build(0, n - 1, 1);int tt = 0;for(int i = 0; i < n; i ++) {scanf("%d", &a[i]);tt += query(a[i], n - 1, 0, n - 1, 1);//看之前插入的有多少个比当前值大 update(a[i], 0, n - 1, 1);//插入当前值 }int ans = tt;for(int i = 0; i < n; i ++) {//递推求最小逆序对数 tt += (n - 1 - a[i]) - a[i];//每次移动最前面那个数,就增加(n-1-a[i])个逆序对,减少(a[i])个逆序对 ans = min(ans, tt);}cout << ans << endl;}return 0;}













0 0
原创粉丝点击