超车(求逆序对个数)
jzabc除了对多米诺骨牌感兴趣外,对赛车也很感兴趣。上个周末他观看了一场赛车比赛。他总是能想出许多稀奇的问题。某一时刻,他看到有n辆车(总是匀速行驶)在同一直线上,并且处在一个无限长度的直道上,而且n辆车有严格的先后之分。他通过特殊的器材测出了每一辆车的速度。那么问题出现了,如果有两辆车A车和B车,A车在B车的后面,并且A车的速度比B车的快,那么经过一段时间后,A车一定会超过B车。我们称之为一次超车。那么他想请你帮忙计算超车总数。我们记车道起点的坐标为0。没有两辆车的坐标相同。
输入格式:
第一行,一个数n,车辆总数。
第二行至第n+1行,为n辆车的信息
每行有两个正整数x,y,x和y之间有一个空格
x为车的坐标,y为车的速度
0<x,y<=1000000000,
输出格式:
一行,超车总数。
样例输入:
2
5 6
2 8
样例输出:
1
题解:
这道题其实就是求逆序对的个数
因为没有两辆车的坐标相同,所以可以先对坐标排序,然后求速度的逆序对个数,就是超车数
=============分割线==============
方法有两个,一个是利用归并排序,排序的次数就是逆序对的个数
还有一个貌似是使用树状数组,有时间再试试吧...
#include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n; long long temp[310000],ans=0;//temp用作存储临时的数据 struct str { long long coo,spe; }a[310000]; bool cmp(str a,str b) { return a.coo<b.coo; } void merge_array(int x,int y)//合并两个数组 { int i=x; int mid=(x+y)/2; int j=mid+1; int k=x; while(i<=mid && j<=y) { if(a[i].spe>a[j].spe) { temp[k++]=a[j++].spe; ans+=mid-i+1; //a[i..mid]已经有序了,那么a[i+1], a[i+2], ... a[mid]都是大于a[j]的, } else temp[k++]=a[i++].spe; } while(i<=mid) temp[k++]=a[i++].spe; while(j<=y) temp[k++]=a[j++].spe; for(int i=x;i<=y;i++) a[i].spe=temp[i]; } void merge_sort(int x,int y) { if(x<y) { int mid=(x+y)/2; merge_sort(x,mid); merge_sort(mid+1,y); merge_array(x,y); } } int main() { ios::sync_with_stdio(false); int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i].coo>>a[i].spe; sort(a+1,a+1+n,cmp); merge_sort(1,n); cout<<ans<<endl; return 0; }