题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1007
题目大意:某个坐标系上有一坨直线,每根直线都表示为kx+b的形式,如果在任意时刻直线i位于最上方,则直线i是可见的,求所有可见直线的编号
这个居然是考试题,惊了
乱搞做法:
开始完全没有任何想法……但是会发现:任意两条k不同的直线都会有一个交点,于是我就脑洞出了做法……首先按k从小到大排序,k相同的留下b最大的一条即可,然后开始暴力找……
找到第一条,然后从它后面的找出一条和它相交最早的一条直线,如果有多条直线在同一时刻和它相交,只留那条k最大的,然后再把找到的这条直线作为开始的直线,再次向后暴力找(前面的不用管了),重复刚才的做法……直至找不到一条可以超过它的直线为止
时间复杂度O(n^2-出题人的良心) bzoj可AC233333
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define INF 2147483647
using namespace std;
struct man
{
int k,b,s;
}a[200000];
int ans[200000];
bool cmp(man x,man y)
{
if(x.k != y.k)
return x.k < y.k;
return x.b < y.b;
}
int main()
{
int n,cnt = 0,maxn = 0;
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&a[i].k,&a[i].b);
a[i].s = i;
}
sort(a+1,a+n+1,cmp);
for(int i = 1;i ;i )
{
while(a[i+1].k == a[i].k)
i ++;
ans[++cnt] = a[i].s;
int k = 0;
double fast = INF;
for(int j = i+1;j <= n;j ++)
{
double time = (double)(a[j].b - a[i].b)/(a[i].k - a[j].k);
if(time <= fast)
{
fast = time;
k = j;
}
}
i = k;
}
sort(ans+1,ans+cnt+1);
for(int i = 1;i <= cnt;i ++)
cout << ans[i] << " ";
return 0;
}
正确做法:按k从小到大排序,开一个栈,如果下一条直线与top-1的交点横坐标小于与top交点的横坐标,那么就直接删除top,最后栈中的就是答案
代码?不要随便伸手要代码,自己能打出来不是更好吗?再说这题又不是很难(明明是你自己懒打好吗)