在一个广场上有一排沿着东西方向排列的石柱子,阳光从东边以一定的倾角射来(平行光)。有的柱子可能被在他东边的高大的柱子的影子给完全遮挡住了。现在你要解决的问题是求出有多少柱子是没有被完全遮挡住的。
假设每个石柱子是一根细棒,而且都垂直于地面摆放。
Input
输入包含多组数据。每组数据第一行是一个整数N(0<N≤100000),表示柱子的个数。N=0代表输入结束。接下来有N行,每行是两个整数,分别给出每根柱子的水平位置X和高度H(X越大,表示越在西边,0≤X≤10000000,0<H≤10000000保证不会有两根柱子在同一个X坐标上)。最后有一行,以分数的形式给出太阳光与地面的夹角的正切值T/A(1≤A,T≤10)。
Output
对每组数据,输出包含所求数目的一行。
Sample input and output
Sample Input | Sample Output |
---|---|
4 0 3 3 1 2 2 1 1 1/1 0 |
2 |
Hint
输入数据很多,请用scanf
代替cin
。
Source
电子科技大学第六届ACM程序设计大赛 初赛
这道题是一道比较容易的题,但一开始我还以为要用线段树,后来发现没法写。。。
后来一想,发现只要一直维护一个影子的最长坐标就可以过了。
具体做法是先对坐标排序,然后算出最靠左的柱子的影子最右坐标,再算下一个柱子影子的最右坐标,这时候比较这两个坐标,如果第一个大于等于第二个,则二号柱子被挡住,否则二号柱子不被挡住,然后取这两者的 大者,对第三柱子计算,然后再取大者,对第四柱子计算·········
Hit:要用scanf读入,不能用cin。。。。
#include <iostream> #include<stdio.h> #include<string.h> using namespace std; long x[100002]={},h[100003]={}; void quick(long j,long k) { long m,n,c,v; n=j;m=k;c=x[(j+k)/2]; do{ while (x[n]<c) n++; while (x[m]>c) m--; if (n<=m){ v=x[n];x[n]=x[m];x[m]=v; v=h[n];h[n]=h[m];h[m]=v; n++;m--; } }while (n<=m); if (n<k) quick(n,k); if (m>j) quick(j,m); } int main() { long l; scanf("%ld",&l); while (l!=0){ memset(x,0,sizeof(x)); memset(h,0,sizeof(h)); int j; for (j=1;j<=l;j++) scanf("%ld %ld",&x[j],&h[j]); int A,T; scanf("%d/%d",&T,&A); quick(1,l); long num=0; double g=0,f; for (j=1;j<=l;j++){ if (g<(f=x[j]+h[j]*1.0*A/T)){ num++; g=f; } } cout<<num<<endl; scanf("%ld",&l); } return 0; }