【栈】bzoj 1007 水平可见直线
来源:互联网 发布:网络安全员年薪多少 编辑:程序博客网 时间:2024/06/05 10:58
题目链接: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 2147483647using 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,最后栈中的就是答案
代码?不要随便伸手要代码,自己能打出来不是更好吗?再说这题又不是很难(明明是你自己懒打好吗)
1 0
- BZOJ 1007 水平可见直线[单调栈]
- 【栈】bzoj 1007 水平可见直线
- 【BZOJ】1007 水平可见直线
- 【BZOJ】1007 水平可见直线
- BZOJ 1007, 水平可见直线
- BZOJ 1007-水平可见直线
- BZOJ 1007(水平可见直线-斜率排序+栈贪心)
- BZOJ 1007 HNOI 2008 水平可见直线 计算几何+栈
- [BZOJ 1007][HNOI2008]水平可见直线:单调栈
- bzoj 1007: [HNOI2008]水平可见直线(模拟栈)
- bzoj 1007 [HNOI2008] 水平可见直线 题解
- [BZOJ 1007][HNOI2008]水平可见直线
- BZOJ-1007-水平可见直线-HN2008
- BZOJ 1007: [HNOI2008]水平可见直线 几何
- [BZOJ 1007] [HNOI2008]水平可见直线
- BZOJ 1007 [HNOI2008]水平可见直线
- BZOJ 1007 [HNOI2008]水平可见直线
- BZOJ 1007: [HNOI2008]水平可见直线
- adb 用法
- 求数组中未出现的最小正整数
- Icocoapods 官方第三方库管理
- ICE学习(八)-异步方法调用AMI
- 112家IT公司薪水一览表
- 【栈】bzoj 1007 水平可见直线
- 学习英语
- OGRE启动过程详解(OGRE HelloWorld程序原理解析)
- 常用端口号
- ORACLE日期时间函数大全
- 二叉搜索树的中序遍历排序
- SQLite Expert professional 修改列名
- 互联网专家资源分享(二)
- 九度OJ 1102:最小面积子矩阵 (DP、缓存、剪枝)