HDU1394(Minimum Inversion Number)

题目地址:Minimum Inversion Number

题目大意:

求逆序对数,求循环移位后逆序数的最小值,意思一次将第一位移到最后一位,然后计算逆序对数,求出最小的那个。

解题思路:

数组数组。

线段树代码。

代码:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <sstream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <string>
 8 #include <bitset>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <cmath>
13 #include <list>
14 //#include <map>
15 #include <set>
16 using namespace std;
17 /***************************************/
18 #define ll long long
19 #define int64 __int64
20 #define PI 3.1415927
21 /***************************************/
22 const int INF = 0x7f7f7f7f;
23 const double eps = 1e-8;
24 const double PIE=acos(-1.0);
25 const int d1x[]= {0,-1,0,1};
26 const int d1y[]= {-1,0,1,0};
27 const int d2x[]= {0,-1,0,1};
28 const int d2y[]= {1,0,-1,0};
29 const int fx[]= {-1,-1,-1,0,0,1,1,1};
30 const int fy[]= {-1,0,1,-1,1,-1,0,1};
31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1};
32 const int diry[]= {-2,-2,-1,-1,1,1,2,2};
33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/
34 /***************************************/
35 void openfile()
36 {
37     freopen("data.in","rb",stdin);
38     freopen("data.out","wb",stdout);
39 }
40 priority_queue<int> qi1;
41 priority_queue<int, vector<int>, greater<int> >qi2;
42 /**********************华丽丽的分割线,以上为模板部分*****************/
43 const int M=5010;
44 int c[M];
45 int n;
46 int lowbit(int x)
47 {
48     return x&(-x);
49 }
50 int sum(int x)
51 {
52     int ret=0;
53     while(x>0)
54     {
55         ret+=c[x];
56         x-=lowbit(x);
57     }
58     return ret;
59 }
60 void add(int x,int val)
61 {
62     while(x<=n)
63     {
64         c[x]+=val;
65         x+=lowbit(x);
66     }
67 }
68 int main()
69 {
70     int a[M];
71     while(scanf("%d",&n)!=EOF)
72     {
73         int i,j;
74         int cnt=0;
75         memset(c,0,sizeof(c));
76         memset(a,0,sizeof(a));
77         for(i=0;i<n;i++)
78         {
79             scanf("%d",&a[i]);
80             a[i]++;
81             cnt+=sum(n)-sum(a[i]);
82             add(a[i],1);
83         }
84         int min=cnt;
85         for(int i=0;i<n;i++)
86         {
87             cnt+=n-a[i]-(a[i]-1);
88             if(cnt<min)
89                 min=cnt;
90         }
91         printf("%d\n",min);
92     }
93     return 0;
94 }

时间: 2025-01-01 21:33:37

HDU1394(Minimum Inversion Number)的相关文章

【HDU1394】Minimum Inversion Number(线段树)

大意:n次操作原串查询逆序数,求出所有串中最小的逆序数. 求逆序数属于线段树的统计问题,建立空树,每次进行插点时进行一次query操作即可.n次操作可以套用结论:如果是0到n的排列,那么如果把第一个数放到最后,对于这个数列,逆序数是减少a[i],而增加n-1-a[i]. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int maxn = 5e3 + 10; 6 int sumv[

【hdu1394】Minimum Inversion Number

Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of

hdu 1394 Minimum Inversion Number(线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10853    Accepted Submission(s): 6676 Problem Description The inversion number of a given number sequence a1, a2, ..., a

HDU 1394 Minimum Inversion Number(线段树求逆序数)

题目地址:HDU 1394 这题可以用线段树来求逆序数. 这题的维护信息为每个数是否已经出现.每次输入后,都从该点的值到n-1进行查询,每次发现出现了一个数,由于是从该数的后面开始找的,这个数肯定是比该数大的.那就是一对逆序数,然后逆序数+1.最后求完所有的逆序数之后,剩下的就可以递推出来了.因为假如目前的第一个数是x,那当把他放到最后面的时候,少的逆序数是本来后面比他小的数的个数.多的逆序数就是放到后面后前面比他大的数的个数.因为所有数都是从0到n-1.所以比他小的数就是x,比他大的数就是n-

HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由[1,N]构成,可以通过旋转把第一个移动到最后一个. 问旋转后最小的逆序数对. 分析: 注意,序列是由[1,N]构成的,我们模拟下旋转,总的逆序数对会有规律的变化. 求出初始的逆序数对再循环一遍就行了. 至于求逆序数对,我以前用归并排序解过这道题:点这里. 不过由于数据范围是5000,所以完全可以用线

HDU 1394 Minimum Inversion Number(线段树求逆序数啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For a given sequence of numbers a1, a2, ..., an,

HDU 1394——Minimum Inversion Number(最小逆序数)

题意: 给定一个序列,里面的数是0到n-1,  每次要把第一个数放到最后一个数,重复n次,求n次操作中最小的逆序数是多少? 思路: 先求出初始的逆序数,然后每移动第一个数到最后面,那么逆序数要减去比它小的数的个数,加上比它大的数的个数. 如果我输入的数是a[i],那么比它小的数的个数就有a[i]个,比它大的数的个数就有n-1-a[i]个 方法:    归并排序 ,树状数组,线段树 归并排序代码: #include<iostream> #include<cstring> #inclu

HDU 1394 Minimum Inversion Number(线段树求逆序对)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1394 解题报告:给出一个序列,求出这个序列的逆序数,然后依次将第一个数移动到最后一位,求在这个过程中,逆序数最小的序列的逆序数是多少? 这题有一个好处是输入的序列保证是0 到 n-1,所以不许要离散化,还有一个好处就是在计算在这个序列中比每个数大和小的数一共有多少个的时候可以在O(1)时间计算出来,一开始我没有意识到,还傻傻的用了两层for循环来每次都计算,当然这样果断TLE了.把一个数从第一个移

HDU 1394 Minimum Inversion Number(逆序数)

题目链接:HDU 1394 Minimum Inversion Number [题意]给你一个1~N的数字组成的初始序列,然后每一次都将第一个数字移到最后,形成新的序列,然后求出这些序列的逆序数中的最小值. [思路]开始可以用任意一种方法(线段树 or 暴力 or 树状数组)计算出初始数列的逆序数sum,这里我比较懒,就直接用的暴力找的sum,对于a[i](0~~n-1),每挪一个,用sum减去挪之前它右边比它小的数的个数(也就是a[i]个),再用sum加上挪之后左边比它大的数的个数(也就是n-