標籤:style blog http color io os ar for sp
題目連結
題意:n個建築物,Q條詢問,問所在的位置,看到天空的角度是多少,每條詢問的位置左右必定是有建築物的。
思路 : 維護一個單調棧,將所有的建築物和所有的人都放到一起開始算就行,每加入一個人,就維護棧裡的建築物的高度,也就是說這個人所能夠看到的建築物時在棧裡的,但是這個人看不到的就刪掉,例如,中間三個點可以刪掉了,因為角度問題中間三個是看不到的,所以不會影響最終求得角度
還有一種情況,就是下述的情況,不停的維護單調棧,人站在不同的地方角度也是不一樣的。
維護的是相鄰兩建築頂(xi,hi)的連線的斜率的絕對值上升 的單調棧。
從左往右一遍,右往左一遍。
是代碼中judge函數的圖,要判斷是否建築物被另一建築物遮擋。
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <iostream> 5 #include <stack> 6 #include <algorithm> 7 #define PI acos(-1.0) 8 using namespace std ; 9 10 struct node11 {12 int pos ;13 int height ;14 bool operator <(const node &a)const15 {16 return pos < a.pos ;17 }18 } p[401210],stk[401210];19 double sh[401010] ;20 int T,n,q;21 22 23 int judge(node &a,node &b,node c){//判斷在c處的視野中,a建築物是否能夠在c處沒有被b建築物擋住24 if(c.height <= 0) c.height = 0 ;25 return (long long)(a.height-c.height)*(c.pos-b.pos) >= (long long)(b.height-c.height)*(c.pos-a.pos) ;26 }27 28 double angle(node a,node b)//求a建築物與b處所成角的大小29 {30 return atan((double)(b.pos-a.pos)/(double)(a.height)) ;31 }32 void solve()33 {34 int top = 0 ;35 for(int i = 0 ; i < n+q ; i ++){36 if(p[i].height <= 0){//是人的地方37 while(top >= 2 && judge(stk[top-2],stk[top-1],p[i])) top -- ;//如果top-1擋不住top-2的話,說明top-1在角度貢獻上沒什麼用38 sh[-p[i].height] += angle(stk[top-1],p[i]) ;39 }40 else41 {42 while(top && stk[top-1].height <= p[i].height) top-- ;//如果棧頂元素沒有新的這個高,那麼肯定會被擋到,所以沒有用刪掉43 while(top >= 2 && judge(stk[top-2],stk[top-1],p[i])) top--;//把這三個建築物的最高點相連,若是凹的,中間那個肯定會被擋到,刪掉44 stk[top++] = p[i] ;45 }46 }47 }48 int main()49 {50 scanf("%d",&T) ;51 int casee = 1 ;52 while(T--)53 {54 scanf("%d",&n) ;55 for(int i = 0 ; i < n ; i++)56 {57 scanf("%d %d",&p[i].pos,&p[i].height) ;58 }59 scanf("%d",&q) ;60 for(int i = 0 ; i < q ; i++)61 {62 scanf("%d",&p[i+n].pos) ;63 p[i+n].height = -i ;//輸出方便64 }65 memset(sh,0,sizeof(sh)) ;66 sort(p,p+n+q) ;67 solve() ;68 reverse(p,p+n+q) ;69 for(int i = 0 ; i < n+q ; i++)//把後邊的全部都移到前邊去,與上邊的統一,方便調用函數70 p[i].pos = 10000000 -p[i].pos ;71 solve() ;72 printf("Case #%d:\n",casee++) ;73 for(int i = 0 ; i < q ; i++){74 printf("%.10lf\n",sh[i]*180/PI) ;//角度與弧度的轉化75 }76 }77 return 0 ;78 }View Code
HDU 5033 Building (維護單調棧)