事实是,我们有N对整数,例如:
23 65
45 66
22 65
80 20
30 11
11 20
我们说如果一对中的两个数字都大于另外两个,或者如果第一个数字相等而另一个数字更大,或者反之亦然,则一对比另一个更大。否则,如果你不能用那种方式比较它们,那么就无法确定哪一个更大。
这个想法是知道,对于每一对,它更大的对数(在这个例子中,第一对比第三对和最后一对更大,因此第一对的答案是2)。 简单的解决方案是O(n 2 ),它只是将每对与每一对进行比较,并为每个正匹配将一个加到计数器中。
任何人都可以提出更快的想法吗?
我已经实现了简单的解决方案(N 2 ),读作来自“sumos.in”:
#include <iostream>
#include <fstream>
#define forn(i, x, N) for(i=x; i<N; i++)
using namespace std;
ifstream fin("sumos.in");
ofstream fout("sumos.out");
struct sumo{
int peso, altura;
};
bool operator < (sumo A, sumo B) {
if( A.altura == B.altura )
if( A.peso < B.peso )
return true;
else
return false;
else
if( A.peso == B.peso )
if( A.altura < B.altura )
return true;
else
return false;
else
if( (A.altura < B.altura) && (A.peso < B.peso) )
return true;
else
return false;
}
int L;
sumo T[100000];
int C[100000];
int main()
{
int i, j;
fin >> L;
forn(i, 0, L)
fin >> T[i].peso >> T[i].altura;
forn(i, 0, L)
forn(j, 0, L)
if( j!=i )
if( T[j]<T[i] )
C[i]++;
forn(i, 0, L)
fout << C[i] << endl;
return 0;
}
输入示例:
10
300 1500
320 1500
299 1580
330 1690
330 1540
339 1500
298 1700
344 1570
276 1678
289 1499
输出:
1
2
1
6
3
3
2
5
0
0
我通过使用分段树解决了这个问题。如果您希望看到实施:http://pastebin.com/Q3AEF1WY
答案 0 :(得分:0)
我想我想出了一个解决方案,但它相当复杂。基本思想是存在这些组,其中对可以按主导顺序排列,例如:
11 20 30 11
22 65 80 20
23 65
45 65
如果你开始考虑接受你的配对并试图创建这些分组,你会发现你最终会得到一个树形结构。例如,想象我们将对81 19添加到列表中并添加一对(-∞,-∞)
(-∞, -∞)
/ \
11 20 30 11 ---\
22 65 80 20 81 19
23 65
45 65
如果您遵循从节点到根的路径,您将计算当前对占主导地位的对数。从这个例子看,你可以使用二进制搜索来确定在结构中插入一对的位置。这就是复杂问题开始的地方。您不能在链表上进行二进制搜索/插入。但是,您可能会使用称为skip list的非常简洁的数据结构。您基本上可以在O(logn)时间内搜索和插入。
还有一个问题。如果有大量的这些分组怎么办?想象一下像
这样的清单11 20
12 19
13 18
14 17
你的树结构看起来像:
(-∞, -∞)
/ / \ \
11 20 12 19 13 18 14 17
再次使用跳过列表来订购这些节点。我认为这将需要树中的两种不同类型的节点,如上面的水平类型和第一个示例中的垂直类型。完成树的构建后,在记录当前深度的同时,使用DFS迭代树,以将每对与其占据的节点数相关联。
如果上述算法是正确的,您可以在O(logn)时间内将该对插入树中,从而将所有对插入O(nlogn)时间。 DFS部分将花费O(n)时间从而构造树并且将一对与其支配的数量相关联将花费O(nlogn)时间。您可以根据O(nlogn)时间中的支配数对对进行排序,这样整个过程将花费O(nlogn)时间。
同样可能有一种更简单的方法可以做到这一点。祝好运!
答案 1 :(得分:-1)
你可以使用。一种。像这样
int z = {23,65,45, 66,22,65,80,20,30,11,11, 20};
int i,j,k,tmp;
for (i=1; i<n; i++){
j= n-i-1;
for (k=0; k<=j; k++)
//注意这个块。
if (z[k]>z[k+1]){
tmp= z[k];
z[k]= z[k+1];
z[k+1]= tmp;
}
}