Problem Description
During Frosh Week, students play various fun games to get to know each other and compete against other teams. In one such game, all the frosh on a team stand in a line, and are then asked to arrange themselves according to some criterion, such as their height, their birth date, or their student number. This rearrangement of the line must be accomplished only by successively swapping pairs of consecutive students. The team that finishes fastest wins. Thus, in order to win, you would like to minimize the number of swaps required.
 
Input
The first line of input contains one positive integer n, the number of students on the team, which will be no more than one million. The following n lines each contain one integer, the student number of each student on the team. No student number will appear more than once. 
 
Output
Output a line containing the minimum number of swaps required to arrange the students in increasing order by student number. 
 
Sample Input
3 3 1 2
 
Sample Output
2
 
分析题意后发现是一个求逆序数的问题
给一列数A[1],A[2],…,A[n],求它的逆序数,即有多少个有序对(i,j),使得i<j但A[i]>A[j]。
受归并排序启发,用分治法解决该问题,把序列分成元素个数尽量相等的两半,递归统计i和j均在左边或者均在右边的逆序数,再统计i在左边,但j在右边的逆序数。
对于i在左边,j在右边的分类,按照j的不同把这些“跨越两边”的逆序对进行分类,只要对于右边的每个j,统计左边比它大的元素个数cnt,则所有cnt之和便是答案。归并排序时,当右边的A[j]复制到辅助数组ass中时,左边还没来得及复制到ass的那些数就是左边所有比A[j]大的数。此时cnt加上左边元素个数mid-p即可(左边所剩的元素在区间[p,mid)中,因此元素个数为mid-p)。
 
归并排序:
(1)划分问题:把序列分成元素个数尽量相等的两半。
(2)递归求解:把两半元素分别进行归并排序。
(3)合并问题:把两个有序表合并成一个。合并时每次只需要把两个序列的最小元素加以比较,删除其中的较小元素并加入合并后的新表即可。
 
注意小细节
(1)代码中使用的左闭右开区间,用左闭右开区间来表示一个范围,好处是在处理“数组分割”时比较自然,区间[low,high)被分成的是[low,mid)和[mid,high),不需要在任何地方加减1(主函数中调用时high要赋上n+1),另外,空区间表示为[x,x),比[x,x-1]顺眼多了。
(2)分界点mid=low+(high-low)/2而不是(low+high)/2,数学上两者相等,但在计算机中却有差别,运算符“/”的取整是朝零方向的取整,用low+(high-low)/2来确保分界点总是靠近区间起点(虽然在这题中并非必要),还有一点,使用mid=low+(high-low)/2还可以避免low+high在low和high很大时可能会出现的溢出。
(3)/2用>>1实现
 #include <stdio.h>
#define MAX 1000000 int arr[MAX+],ass[MAX+];
__int64 cnt; void MergeSort(int low,int high){
int mid,p,q,i;
if(high-low==)
return;
mid=low+((high-low)>>);
MergeSort(low,mid);
MergeSort(mid,high);
p=low,q=mid,i=low;
while(p<mid||q<high){
if(q>=high||(p<mid&&arr[p]<=arr[q]))
ass[i++]=arr[p++];
else{
ass[i++]=arr[q++];
cnt+=mid-p;
}
}
for(i=low;i<high;i++)
arr[i]=ass[i];
} void scani(int &num){
char ch;
int flag;
while(ch=getchar(),(ch>''||ch<'')&&(ch!='-'));
if(ch=='-')
flag=-,num=;
else
flag=,num=ch-'';
while(ch=getchar(),ch<=''&&ch>='')
num=num*+ch-'';
num*=flag;
} int main(){
int n,i;
while(~scanf("%d",&n)){
for(i=;i<=n;i++)
scani(arr[i]);
cnt=;
MergeSort(,n+);
printf("%I64d\n",cnt);
}
return ;
}

Frosh Week的更多相关文章

  1. HDU 3743 Frosh Week (线段树+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other) ...

  2. UVA 11858 Frosh Week 逆序对统计

    题目链接: http://acm.hust.edu.cn/vjudge/contest/122094#problem/H Frosh Week Time Limit:8000MSMemory Limi ...

  3. 暑假集训(2)第六弹 ----- Frosh Week(UVA11858)

    H - Frosh Week Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     ...

  4. 问题 C: Frosh Week(2018组队训练赛第十五场)(签到)

    问题 C: Frosh Week 时间限制: 4 Sec  内存限制: 128 MB提交: 145  解决: 63[提交][状态][讨论版][命题人:admin] 题目描述 Professor Zac ...

  5. Frosh Week(归并排序求逆序数)

    H - Frosh Week Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Desc ...

  6. HDU 3743 Frosh Week(归并排序求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 题目意思就是给你一个长为n的序列,让你求逆序对.我用的是归并排序来求的.归并排序有一个合并的过程 ...

  7. HDU 3743 Frosh Week(归并排序求逆序数)

    归并排序求逆序数 #include <iostream> #include <cstdio> using namespace std; #define maxn 1000005 ...

  8. Frosh Week HDU3743(逆序数)

    离散化加 求逆序数: 求逆序数的方法 一个是归并排序  一个是树状数组 #include<bits/stdc++.h> using namespace std; int n; struct ...

  9. Prerequisites?[HDU1144]

    Prerequisites?Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...

随机推荐

  1. ORACLE-SQL(二)

      CreateTime--2017年6月1日14:36:37 Author:Marydon 一.SQL语句 (二)提升篇 1.2.3 分页,分组,计数,排序 /** * 返回数据 * FORGID ...

  2. 计算机顶级会议Rankings &amp;&amp; 英文投稿的一点经验

    英文投稿的一点经验[转载] From: http://chl033.woku.com/article/2893317.html 1. 首先一定要注意杂志的发表范围, 超出范围的千万别投,要不就是浪费时 ...

  3. 18、Java中可变参数

    从JDK 1.5之后,Java允许定义形参可变的参数 例如: public void test(int a,String ... books){ for(String book:books){ Sys ...

  4. (二)Linux Shell编程——运算符、注释

    2.7 Shell运算符 Bash 支持很多运算符,包括算数运算符.关系运算符.布尔运算符.字符串运算符和文件测试运算符.原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 ...

  5. struts2 中请求转发与请求重定向方法

    本文转自:http://blog.csdn.net/a327736051/article/details/50240491 一.Chain Result:这个result调用另外的一个action,连 ...

  6. HDUOJ----(4706)Children's Day

    Children's Day Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. 给你出道题:依次去掉离中心最远的M个点

    给定一个数组a[N],里面包含N个向量.现在要求进行删点操作,删点原则如下: 1.求出N个向量的中心O1,删除离O1最远的那个点 2.求出N-1个向量的中心O2,删除O2最远的那个点 ...... 重 ...

  8. Windows右键菜单设置与应用技巧

    http://blog.163.com/lee_honleon/blog/static/555251522008014258896/   需要修改注册表,挺麻烦的.最好还是把迅雷卸了重装,不会影响什么 ...

  9. Linux命令-终止进程命令:kill

    kill -l 查看进程信号 常用信号 例如: 例子参见:Linux命令-查看进程命令:pstree

  10. Linux基础之常用命令篇

    一.命令的基本格式 [root@localhost~] root为用户名 -表示当前所在位置 localhost主机名 ‘#’超级用户 '$" 普通用户 命令的基本格式: 命令 [选项] [ ...