给出N个人在0时刻的财富值M[i](所有人在0时刻的财富互不相等),以及财富增长速度S[i],随着时间的推移,某些人的财富值会超越另外一些人。如果时间足够长,对于财富增长最快的人来说,他的财富将超越所有其他对手。
求发生的前10000次超越,分别是谁超过了谁?如果总的超越次数不足10000,则输出所有超越,如果1次超越都不会发生,则输出No Solution。
输出按照超越发生的时间排序,同一时刻发生的超越,按照超越者的编号排序,如果编号也相同,则按照被超越者的编号排序。所有排序均为递增序。
Input
第1行:N,表示人的数量。(1 <= N <= 10000) 第2 - N + 1行:每行2个数,分别是初始的财富值M[i],和财富增长速度S[i]。(0 <= M[i] <= 10^5, 1 <= S[i] <= 100)
Output
输出前10000次超越,超越者和被超越者的编号。如果总的超越次数不足10000,则输出所有。如果1次超越都不会发生,则输出No Solution。 输出按照超越发生的时间排序,同一时刻发生的超越,按照超越者的编号排序,如果超越者编号也相同,则按照被超越者的编号排序。所有排序均为递增序。
Input示例
4 1 100 2 100 3 1 4 50
Output示例
2 3 1 3 2 4 1 4
李陶冶
(题目提供者)
这题可以简单转化为求直线交点问题,当且仅当财富值m[i]<m[j]并且增长值s[i]>s[j]时才会发生超越
因此 find函数里找到当前时间下,每个点超越(或者被超越了几次)->这里二分一下即可,剩下的用
一个优先队列存储即可(n^2存点,侥幸通过)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<limits.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<math.h>
#include<string>
#include<map>
using namespace std;
#define maxn 10005
#define eps 1e-8
using namespace std;
struct Res
{
int b,k,id;
bool operator <(const Res &c) const
{
if(b>c.b)
return 1;
return 0;
}
}s[maxn];
struct Coin
{
double y;
int id;
bool operator <(const Coin &b) const
{
if(y>b.y)
return 1;
return 0;
}
}c[maxn];
struct Point
{
double p;
int x,y;
bool operator <(const Point &b) const
{
if(p>b.p || fabs(p-b.p)<eps && x>b.x || fabs(p-b.p)<eps && x==b.x && y>b.y)
return 1;
return 0;
}
}now;
priority_queue<Point>q;
int n;
int find(double x)//判断x秒时,每个人的财富超过了多少人的财富
{
int i,sum=0;
for(i=1;i<=n;i++)
{
c[i].id=i;
c[i].y=s[i].b+s[i].k*x;
}
sort(c+1,c+n+1);
for(i=1;i<=n;i++)
if(i<c[i].id)//表明这个人超过了一定数量的人
sum+=c[i].id-i;
return sum;
}
int main()
{
int i,j;
double x,l,r,m;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d",&s[i].b,&s[i].k);
s[i].id=i;
}
sort(s+1,s+n+1);
l=1;r=1000005;
while(r-l>0.00001)
{
m=(l+r)/2;
if(find(m)>10000)
r=m;
else
l=m;
}
for(i=2;i<=n;i++)
for(j=1;j<i;j++)
{
x=1.0*(s[j].b-s[i].b)/(s[i].k-s[j].k);
if(x>eps && x<r)
{
now.p=x;
now.x=s[i].id;
now.y=s[j].id;
q.push(now);
}
}
for(i=1;i<=10000;i++)
{
if(!q.empty())
{
printf("%d %d\n",q.top().x,q.top().y);
q.pop();
}
else
break;
}
}