HDU 1394 Minimum Inversion Number 线段树

本文针对HDU 1394题目提供了解决方案,采用区间树进行逆序对计数,实现快速查找及更新。通过具体代码展示了如何使用区间树的数据结构来优化算法效率。

题目: http://acm.hdu.edu.cn/showproblem.php?pid=1394

没看到多组输入,WA了一万次。。。。。。

其实很简单,有人暴力过得,我感觉归并排序、二叉排序树求逆序数都可以,但是我没写。

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 const int MAXN = 5010;
 5 
 6 struct Tree_Node
 7 {
 8     int left, right;
 9     int num;
10 } tree[MAXN<<3];
11 
12 void build(int left, int right, int step)
13 {
14     tree[step].left = left;
15     tree[step].right = right;
16     tree[step].num = 0;
17     if(left == right)
18         return;
19     int mid = (left + right) >> 1;
20     build(left, mid, step<<1);
21     build(mid+1, right, step<<1|1);
22 }
23 
24 void insert(int cur, int step)
25 {
26     if(cur >= tree[step].left && cur <= tree[step].right)
27         tree[step].num++;
28     if(tree[step].left == tree[step].right)
29         return;
30     int mid = (tree[step].left + tree[step].right) >> 1;
31     if(cur <= mid)
32         insert(cur, step<<1);
33     else
34         insert(cur, step<<1|1);
35 }
36 
37 int query(int left, int right, int step)
38 {
39     if(tree[step].left == left && tree[step].right == right)
40     {
41         return tree[step].num;
42     }
43     int mid = (tree[step].left + tree[step].right) >> 1;
44     if(right <= mid)
45     {
46         return query(left, right, step<<1);
47     }
48     else if(left > mid)
49     {
50         return query(left, right, step<<1|1);
51     }
52     else
53     {
54         return query(left, mid, step<<1) + query(mid+1, right, step<<1|1);
55     }
56 }
57 
58 int main()
59 {
60     int n, x[MAXN];
61     while(scanf("%d", &n) != EOF)
62     {
63         int ans = 0;
64         build(0, n, 1);
65         for(int i = 0; i < n; i++)
66         {
67             scanf("%d", &x[i]);
68             ans += query(x[i]+1, n, 1);
69             insert(x[i], 1);
70         }
71         int tmp = ans;
72         for(int i = 0; i < n; i++)
73         {
74             tmp += n - x[i] - x[i] - 1;
75             if(tmp < ans)ans = tmp;
76         }
77         printf("%d\n", ans);
78     }
79     return 0;
80 }
View Code

 

转载于:https://www.cnblogs.com/wolfred7464/p/3411346.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值