首页 > 其他 > 详细

HDU 1394Minimum Inversion Number(线段树)

时间:2014-08-01 13:19:11      阅读:293      评论:0      收藏:0      [点我收藏+]

题目大意是说给你一个数组(N个),没戏可以将其首部的k(k<N)个元素移动至尾部,这样总共会形成N个序列

现在要求这n个序列中逆序对数最少的那一个序列有多少个逆序对

 

最初的确是没太多思路,就算知道线段书可以球某一个序列的逆序对数,但是这里要求n次,就没有太多把握了

而最后的方法其实的确是只用求一次的,由于给出的n个数字是0~n-1的一个排列,所以考虑吧a[0]放到最后一个位置时,那以它作为起点的逆序对数相应的会减少a[0]个(这是因为塔处在地一个位置,所有比它晓得数都会在其后方), 然后考虑a[0]已经被移动到最后一个位置,那么相应的这个序列的逆序对数会增加n-a[0]个

所以只要在一遍线段书或树状数组求出开始时的逆序对数后,后面的可以由它递推得到

 

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <vector>
 8 #include <cstdio>
 9 #include <cctype>
10 #include <cstring>
11 #include <cstdlib>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 #define INF 1e9
16 #define inf (-((LL)1<<40))
17 #define lson k<<1, L, mid
18 #define rson k<<1|1, mid+1, R
19 #define mem0(a) memset(a,0,sizeof(a))
20 #define mem1(a) memset(a,-1,sizeof(a))
21 #define mem(a, b) memset(a, b, sizeof(a))
22 #define FOPENIN(IN) freopen(IN, "r", stdin)
23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
24 template<class T> T CMP_MIN(T a, T b) { return a < b; }
25 template<class T> T CMP_MAX(T a, T b) { return a > b; }
26 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
27 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
28 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
29 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
30 
31 typedef __int64 LL;
32 //typedef long long LL;
33 const int MAXN = 5005;
34 const int MAXM = 100005;
35 const double eps = 1e-10;
36 const LL MOD = 1000000007;
37 
38 int c[MAXN], a[MAXN], id[MAXN], N;
39 
40 int lowbit(int x)
41 {
42     return x & (-x);
43 }
44 
45 void update(int k, int x)
46 {
47     while(k <= N)
48     {
49         c[k] += x;
50         k += lowbit(k);
51     }
52 }
53 
54 int getSum(int k)
55 {
56     int sum = 0;
57     while(k > 0)
58     {
59         sum += c[k];
60         k -= lowbit(k);
61     }
62     return sum;
63 }
64 
65 int cmp(int i, int j)
66 {
67     return a[i] > a[j];
68 }
69 
70 int getCnt()
71 {
72     for(int i=1;i<=N;i++) id[i] = i;
73     sort(id+1, id + N + 1, cmp);
74     mem0(c);
75     int cnt = 0;
76     for(int i=1;i<=N;i++)
77     {
78         cnt += getSum(id[i]);
79         update(id[i], 1);
80     }
81     return cnt;
82 }
83 
84 int main()
85 {
86     while(scanf("%d", &N) == 1)
87     {
88         for(int i=1;i<=N;i++) scanf("%d", &a[i]);
89         int ans = getCnt(), x = ans;
90         for(int i=1;i<N;i++)
91         {
92             x = x + N - 2 * a[i] - 1;
93             ans = MIN(ans, x);
94         }
95         printf("%d\n", ans);
96     }
97     return 0;
98 }

 

HDU 1394Minimum Inversion Number(线段树),布布扣,bubuko.com

HDU 1394Minimum Inversion Number(线段树)

原文:http://www.cnblogs.com/gj-Acit/p/3884639.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!