Time Limit: 10000/3000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
在一个广场上有一排沿着东西方向排列的石柱子,阳光从东边以一定的倾角射来(平行光)。有的柱子可能被在他东边的高大的柱子的影子给完全遮挡住了。现在你要解决的问题是求出有多少柱子是没有被完全遮挡住的。
假设每个石柱子是一根细棒,而且都垂直于地面摆放。
Input
输入包含多组数据。每组数据第一行是一个整数,表示柱子的个数。代表输入结束。接下来有行,每行是两个整数,分别给出每根柱子的水平位置X和高度(越大,表示越在西边,保证不会有两根柱子在同一个X坐标上)。最后有一行,以分数的形式给出太阳光与地面的夹角的正切值。
Output
对每组数据,输出包含所求数目的一行。
Sample Input
4
0 3
3 1
2 2
1 1
1/1
0
Sample Output
2
提示:
输入数据很多,请用scanf代替cin。
Source
UESTC 6th Programming Contest Online
题解:
单调栈
按照x的大小从小到大排序,从后往前依此入栈,每次入栈前要保证栈顶的柱子不会被当前放入栈的柱子给完全遮挡。
判断方法:
设当前栈顶的柱子为A,准备入栈的柱子为B
如果A的高度大于等于B,那么A一定不会被B遮挡。
否则
如果∠1的正切值大于等于T/A则A被B覆盖,
否则不被B覆盖最后输出栈内的元素总数即可
#include<bits/stdc++.h>
#define LiangJiaJun main
using namespace std;
int n;
struct Dic{
int a,b;
}V;
struct Ds{
int x,h;
}a[100004];
inline bool dex(Ds A, Ds B){
return A.x<B.x;
}
Ds st[100004];
bool becover(Ds A,Ds B){
if(A.h>=B.h)return 0;
int g=B.h-A.h;
int r=A.x-B.x;
return g*V.b>=V.a*r;
}
int w33ha(){
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].h);
sort(a+1,a+n+1,dex);
scanf("%d/%d",&V.a,&V.b);
int t=1;
st[t]=a[n];
for(int i=n-1;i>=1;i--){
while(t>0&&becover(st[t],a[i]))t--;
st[++t]=a[i];
}
printf("%d\n",t);
return 0;
}
int LiangJiaJun(){
while(scanf("%d",&n)!=EOF){
if(n==0)break;
w33ha();
}
return 0;
}