给出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
以时间为x轴,财富为y轴建立坐标系,则超越就是两条直线的交点且有交点必须满足s[i]>s[j],w[i]<w[j].n条直线最多有n*(n-1)/2条交点,全部储存消耗内存,可以二分时间确定某时刻交点的个数
#include <bits/stdc++.h> using namespace std; #define esp 1e-9 typedef long long ll; int n; struct point{ double w,s; int id; bool operator<(const point &a) const { return a.w>w; } }e[10005]; struct Cost{ double cost; int id; bool operator<(const Cost &a) const { return a.cost>cost; } }f[10006]; struct node { double time; int idx,idy; bool operator<(const node &a)const { return fabs(a.time-time)<esp?(a.idx==idx?a.idy<idy:a.idx<idx):a.time<time; } }p; priority_queue<node>q; int solve(double mid) { for(int i=1;i<=n;i++){ f[i].id=i; f[i].cost=mid*e[i].s+e[i].w; } sort(f+1,f+n+1); int ans=0; for(int i=1;i<=n;i++) if(i<f[i].id) ans+=f[i].id-i; return ans>10000; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf",&e[i].w,&e[i].s); e[i].id=i; } sort(e+1,e+n+1); double l=1.0,r=100000005.0; while(r-l>0.00001){ double mid=(l+r)/2; if(solve(mid)) r=mid; else l=mid; } for(int i=1;i<=n;i++) for(int j=1;j<i;j++) { if(e[j].s>e[i].s) { p.time=(e[i].w-e[j].w)*1.0/(e[j].s-e[i].s); if(p.time>esp && p.time<r) { p.idx=e[j].id; p.idy=e[i].id; q.push(p); } } } for(int i=0;i<10000;i++) { if(!q.empty()){ printf("%d %d ",q.top().idx,q.top().idy); q.pop(); } else break; } return 0; }