51Nod-1112-KGold(直线相交)

来源:互联网 发布:git解决冲突知乎 编辑:程序博客网 时间:2024/05/20 05:31
1112 KGold
题目来源: UVALive 5868
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注
给出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示例
41 1002 1003 14 50
Output示例
2 31 32 41 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-8using 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;elsel=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();}elsebreak;}}


0 0