HDU

题目链接

题意:

给定一个长度为 $n$ 的序列,现在这个序列可以不断地将第一个数放到最后,求过程中最小的逆序对。

思路:

一开始直接硬模拟了一发,结果是显然的。(自闭选手)

可以一开始直接求得原始序列的逆序数,然后考虑每一位往后移的过程中对答案的贡献, 然后取最小值即可。

当第一位的数字移动到最后一位的时候,那么比 $a[1]$ 小的数字的逆序就没有了,而增加了比 $a[1]$ 大的数字的逆序

即每一位数字对答案的贡献为  $n-a[i] - (a[i] - 1)$;

 1 /*
 2 *  Author: windystreet
 3 *  Date  : 2018-08-10 14:36:11
 4 *  Motto : Think twice, code once.
 5 */
 6 #include<bits/stdc++.h>
 7 
 8 using namespace std;
 9 
10 #define X first
11 #define Y second
12 #define eps  1e-5
13 #define gcd __gcd
14 #define pb push_back
15 #define PI acos(-1.0)
16 #define lowbit(x) (x)&(-x)
17 #define bug printf("!!!!!
");
18 #define mem(x,y) memset(x,y,sizeof(x))
19 
20 typedef long long LL;
21 typedef long double LD;
22 typedef pair<int,int> pii;
23 typedef unsigned long long uLL;
24 
25 const int maxn = 5e3+7;
26 const int INF  = 1<<30;
27 const int mod  = 1e9+7;
28 
29 int tree[maxn];
30 int n;
31 void init(){
32     for(int i=0;i<=n;i++)
33         tree[i]=0;
34     return;
35 }
36 void add(int x,int v){
37     for(int i=x;i<=n;i+=lowbit(i))
38         tree[i] += v;
39     return ;
40 }
41 int query(int x){
42     int res = 0;
43     for(int i=x;i;i-=lowbit(i))
44         res += tree[i];
45     return res;
46 }
47 
48 int s[maxn];
49 
50 void solve(){
51     int ans ;
52     while(scanf("%d",&n)!=EOF){
53         init();
54         for(int i=1;i<=n;i++){
55             scanf("%d",&s[i]);
56             ++s[i];
57         }
58         int sum = 0;
59         for(int i=1;i<=n;i++){                    //  计算原始序列的逆序数
60             add(s[i],1);
61             sum += i - query(s[i]);
62         }
63         ans = sum;
64         for(int i=1;i<=n;i++){
65             sum += n - s[i] - (s[i] - 1);        // 对于每一位的贡献更新答案
66             ans = min(ans,sum);                  // 取最优解
67         }
68         printf("%d
",ans);
69 
70     }   
71     return;
72 }
73 
74 int main()
75 {
76 //    freopen("in.txt","r",stdin);
77 //    freopen("out.txt","w",stdout);
78 //    ios::sync_with_stdio(false);
79     int t = 1;
80     //scanf("%d",&t);
81     while(t--){
82     //    printf("Case %d: ",cas++);
83         solve();
84     }
85     return 0;
86 }
原文地址:https://www.cnblogs.com/windystreet/p/9455677.html