hnu 12264 collisions


题目:

Collisions
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB
Total submit users: 10, Accepted users: 7
Problem 12264 : No special judgement
Problem description
Identical small balls are located on a straight line and can move along this line only. Each ball moves with a constant velocity, but velocities of different balls may be different. When two balls meet, a perfectly elastic collision occurs. It’s a common-known physical fact, that when two equal-mass physical bodies A and B collide perfectly elastically, they swap their velocities, i.?e. new A’s velocity is old B’s one, and new B’s is old A’s.
Your task is to write a program to find the total number of collisions.
Input
The first line at input contains the number of balls N (3 ≤ N ≤ 2000000). Each of the following N lines contains 2 space-separated integers — the starting coordinate and the velocity of corresponding ball. All start coordinates are in range -1011 < xi < 1011, all velocities are in range -108 < vi < 108. All start coordinates are different. It’s guaranteed that each collision involves exactly two balls (none involves three or more balls together).
Output
Your program should output exactly one integer number in a single line ? the total number of collisions (or 987654321987654321 if the number is infinite).
Sample Input
3
-5 3
0 -1
7 -2
Sample Output
3
Problem Source

2010 All-Ukrainian Collegiate Programming Contest Vinnytsia National Technical University

题意:就是告诉你有n,个小球,第二行是n个小球的位置和速度,所有小球都在一条直线上,小球相碰后交换速度,问最多有几次碰撞。如果无数次,输出987654321987654321.

思路:开始毫无思路,后来想了一下,相碰后交换速度,不是等价于直接穿过去吗,如果把小球按位置排序,即从小到大排序,然后求速度的逆序数不就行了吗?比如两个小球,一前一后分别为5,4,者后面小球会追上相碰,或者4,-3,也一样,还有,-1,-2,也是那个道理,所以题目就是叫你求逆序数。那样就不会有无数次的情况了,真的吗?答案是对的。求逆序数有两种方法,归并排序和树状数组,至少我知道这两种,不太会用,归并用了个模板,一次就过了,还是挺惊讶的。

代码:

 1 #include<iostream>
2 #include<algorithm>
3 using namespace std;
4 const int size=2000500;
5 __int64 date[size];
6 struct point{
7 __int64 position,v;
8 };
9 point temp[size];
10 int n;
11 __int64 L[size];
12 __int64 R[size];
13 const int Max = 1 <<30;
14 __int64 change = 0;
15 bool cmp(point x,point y)
16 {
17 return x.position<y.position;
18 }
19
20 void Merge(__int64 *data,int left,int divide,int right)
21 {
22 int lengthL = divide - left;
23 int lengthR = right - divide;
24
25 for(int i = 0; i < lengthL; ++i)
26 {
27 L[i] = data[left + i];
28 }
29 for(int i = 0; i < lengthR; ++i)
30 {
31 R[i] = data[divide + i];
32 }
33 L[lengthL] = R[lengthR] = Max;
34 int i = 0;
35 int j = 0;
36 for(int k = left; k < right; ++k)
37 {
38 if(L[i] <= R[j])
39 {
40 data[k] = L[i];
41 ++i;
42 }
43 else
44 {
45 change += divide - i - left ;
46 data[k] = R[j];
47 ++j;
48 }
49 }
50
51 }
52
53 void MergeSort(__int64 *data,int left,int right)//归并排序求逆序数
54 {
55 if(left < right -1)
56 {
57 int divide = (left + right)/2;
58 MergeSort(data,left,divide);
59 MergeSort(data,divide,right);
60 Merge(data,left,divide,right);
61 }
62 }
63
64
65
66 int main()
67 {
68 scanf("%d",&n);
69 for(int i=0;i<n;i++)
70 scanf("%I64d%I64d",&temp[i].position,&temp[i].v);
71 sort(temp,temp+n,cmp);//按位置排序
72 for(int i=0;i<n;i++)
73 date[i]=temp[i].v;
74 MergeSort(date,0,n);
75 cout<<change<<endl;
76 //system("pause");
77 return 0;
78 }

***************************************************************************************

总结:

1.基本代码要会敲,比如归并

2.相信自己,比如不会有无数次的情况

3.多练

最近心情压抑呀

原文地址:https://www.cnblogs.com/xingyezhi/p/2394063.html