码迷,mamicode.com
首页 > 其他好文 > 详细

逆序数2 HDOJ 1394 Minimum Inversion Number

时间:2015-05-10 17:14:39      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

 

题目传送门

1 /*
2     求逆序数的四种方法
3 */
技术分享
 1 /*
 2     1. O(n^2) 暴力+递推 法:如果求出第一种情况的逆序列,其他的可以通过递推来搞出来,一开始是t[1],t[2],t[3]....t[N]
 3     它的逆序列个数是N个,如果把t[1]放到t[N]后面,逆序列个数会减少t[1]个,相应会增加N-(t[1]+1)个  
 4 */
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <algorithm>
 8 using namespace std;
 9 
10 const int MAX_N = 10000 + 10;
11 const int INF = 0x3f3f3f3f;
12 int a[MAX_N];
13 int num[MAX_N];
14 
15 int main(void)      //HDOJ 1394 Minimum Inversion Number
16 {
17     //freopen ("inC.txt", "r", stdin);
18     int n;
19 
20     while (~scanf ("%d", &n))
21     {
22         memset (num, 0, sizeof (num));
23         for (int i=1; i<=n; ++i)
24         {
25             scanf ("%d", &a[i]);
26             //a[n+i] = a[i];
27         }
28         int t = 0;  int sum = 0;
29         for (int i=1; i<=n; ++i)    //先求解最初的数列逆序数
30         {
31             for (int j=i+1; j<=n; ++j)
32             {
33                 if (a[i] > a[j])
34                 {
35                     sum++;
36                 }
37             }
38         }
39         //printf ("%d\n", sum);
40         int ans = INF;
41         for (int i=1; i<=n; ++i)        //更新sum,找最小
42         {
43             sum = sum - a[i] + (n - a[i] - 1);      //the next line contains a permutation of the n integers from 0 to n-1. 
44             //printf ("%d\n", res);                 //从0到n-1的整数  所以这里用a[i]  读题不仔细 。。。。
45             ans = min (sum, ans);
46         }
47         printf ("%d\n", ans);
48     }
49 
50     return 0;
51 }
O(n^2) 暴力+递推
技术分享nlogn归并算法
技术分享
 1 /*
 2     3. nlogn 线段树-单点更新:更新比a[i]大的个数
 3 */
 4 #include <cstdio>
 5 #include <algorithm>
 6 #define lson l, m, rt << 1
 7 #define rson m+1, r, rt << 1 | 1
 8 
 9 const int MAX_N = 5000 + 10;
10 const int INF = 0x3f3f3f3f;
11 int a[MAX_N];
12 int sum[MAX_N << 2];
13 
14 void pushup(int rt)
15 {
16     sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
17 }
18 
19 void build(int l, int r, int rt)
20 {
21     sum[rt] = 0;
22     if (l == r) return ;
23     int m = (l + r) >> 1;
24     build (lson);
25     build (rson);
26 }
27 
28 void update(int p, int l, int r, int rt)
29 {
30     if (l == r)
31     {
32         sum[rt]++;      //记录次数
33         return ;
34     }
35     int m = (l + r) >> 1;
36     if (p <= m)
37     {
38         update (p, lson);
39     }
40     else
41         update(p, rson);
42     pushup (rt);
43 }
44 
45 int query(int ql, int qr, int l, int r, int rt)
46 {
47     if (ql <= l && r <= qr)
48     {
49         return sum[rt];
50     }
51     int m = (l + r) >> 1;
52     int ans = 0;
53     if (ql <= m)    ans += query (ql, qr, lson);
54     if (qr > m)     ans += query (ql, qr, rson);
55 
56     return ans;
57 }
58 
59 int main(void)      //HDOJ 1394 Minimum Inversion Number
60 {
61     //freopen ("inC.txt", "r", stdin);
62     int n;
63     while (~scanf ("%d", &n))
64     {
65         //memset (num, 0, sizeof (num));
66         build (0, n-1, 1);
67         int sum = 0;
68         for (int i=1; i<=n; ++i)   
69         {
70             scanf ("%d", &a[i]);
71             sum += query (a[i], n-1, 0, n-1, 1);
72             update (a[i], 0, n-1, 1);
73         }
74         int ans = sum;
75         for (int i=1; i<=n; ++i)        
76         {
77             sum = sum - a[i] + (n - a[i] - 1);            
78             ans = std::min (sum, ans);
79         }
80         printf ("%d\n", ans);
81     }
82 
83     return 0;
84 }
nlogn 线段树-单点更新
技术分享
 1 /*
 2     4. 树状数组
 3 */
 4 #include <stdio.h>
 5 #include <string.h>
 6 #include <algorithm>
 7 using namespace std;
 8 const int MAXN=5050;
 9 int c[MAXN];
10 int a[MAXN];
11 int n;
12 
13 int lowbit(int x)
14 {
15     return x&(-x);
16 }
17 
18 void add(int i,int val)
19 {
20     while(i<=n)
21     {
22         c[i]+=val;
23         i+=lowbit(i);
24     }
25 }
26 
27 int sum(int i)
28 {
29     int s=0;
30     while(i>0)
31     {
32         s+=c[i];
33         i-=lowbit(i);
34     }
35     return s;
36 }
37 
38 int main()      //HDOJ 1394 Minimum Inversion Number
39 {
40     //freopen ("inC.txt", "r", stdin);
41     while(scanf("%d",&n)!=EOF)
42     {
43         int ans=0;
44         memset(c,0,sizeof(c));
45         for(int i=1;i<=n;i++)
46         {
47             scanf("%d",&a[i]);
48             a[i]++;
49             ans+=sum(n)-sum(a[i]);
50             add(a[i],1);
51         }
52         int Min=ans;
53         for(int i=1;i<=n;i++)
54         {
55             ans+=n-a[i]-(a[i]-1);
56             if(ans<Min)Min=ans;
57         }
58         printf("%d\n",Min);
59     }
60     
61     return 0;
62 }
树状数组



 

逆序数2 HDOJ 1394 Minimum Inversion Number

标签:

原文地址:http://www.cnblogs.com/Running-Time/p/4492456.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!