Walls(扫描线)

Walls

http://poj.org/problem?id=3470

Time Limit: 6000MS   Memory Limit: 131072K
Total Submissions: 2544   Accepted: 378
Case Time Limit: 3000MS

Description

There are N walls. A wall has an infinity height, so it looks like a segment in a plane from high sky. Obviously, they don't intersect. Let's take a series of interesting experiments. Everytime, we put a lovely bird called Xiaoniao in the place. Then, she will choose any one of four possible directions paralleled to axes and disregarded anything else but fly forward. It may occur that she touch a wall and fainted. So poor Xiaoniao is, she always choose the direction which made her fainted as early as possible. You're asked to count, how many times did Xiaoniao touched each wall.

It is guaranteed that each time there will be exactly one direction that makes Xiaoniao faints as early as possible. I.E. She won't have no choice to get faint, neither have more than one direction producing the same fainting time. Xiaoniao won't be placed on a wall, either. Touching an end point of a wall is also considered a touch.

Input

The first line contains N and M (both not exceeding 50,000). M is the number we put Xiaoniao in the place.
The following N lines describe the walls. Each line consists 4 integers x1y1x2y2, meaning a wall from (x1,y1) to (x2,y2). The wall is always parallel to the coordinate axes.
The next M lines describe where we put Xiaoniao. Each line consists 2 integers x and y. This means we put Xiaoniao at the point (x,y).

Output

N lines, i-th line contains one integer that is the number of Xiaoniao touches the i-th wall.

Sample Input

4 4
10 0 10 40
0 40 40 40
10 10 50 10
40 50 40 10
15 12
12 35
35 38
38 15

Sample Output

1
1
1
1

题意:有m只鸟,他们会撞向离自己最近的墙,问每个墙上有多少只鸟的尸体

思路:扫描线从四个方向扫描,遇到墙时插入,遇到鸟时查询即可

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<cmath>
  5 #include<cstdio>
  6 #define maxn 600005
  7 #define lson l,mid,rt<<1
  8 #define rson mid+1,r,rt<<1|1
  9 #define pb push_back
 10 const double eps=1e-8;
 11 const double PI=acos(-1.0);
 12 using namespace std;
 13 
 14 int tree[maxn];
 15 int lazy[maxn];
 16 vector<int>ve[2];
 17 int k;
 18 int sgn(double x){
 19     if(fabs(x)<eps) return 0;
 20     if(x<0) return -1;
 21     else return 1;
 22 }
 23 inline double hypot(double a,double b){return sqrt(a*a+b*b);}
 24 struct Point{
 25     double x,y;
 26     Point(){}
 27     Point(double _x,double _y){
 28         x=_x;
 29         y=_y;
 30     }
 31     Point operator - (const Point &b)const{
 32         return Point(x-b.x,y-b.y);
 33     }
 34     //叉积
 35     double operator ^ (const Point &b)const{
 36         return x*b.y-y*b.x;
 37     }
 38     //点积
 39     double operator * (const Point &b)const{
 40         return x*b.x+y*b.y;
 41     }
 42     //返回两点的距离
 43     double distance(Point p){
 44         return hypot(x-p.x,y-p.y);
 45     }
 46     Point operator * (const double &k)const{
 47         return Point(x*k,y*k);
 48     }
 49     Point operator / (const double &k)const{
 50         return Point(x/k,y/k);
 51     }
 52 };
 53 
 54 struct Line{
 55     Point s,e;
 56     Line(){}
 57     Line(Point _s,Point _e){
 58         s=_s;
 59         e=_e;
 60     }
 61     //求线段长度
 62     double length(){
 63         return s.distance(e);
 64     }
 65     double dispointtoline(Point p){
 66         return fabs((p-s)^(e-s))/length();
 67     }
 68     //点到线段的距离
 69     double dispointtoseg(Point p){
 70         if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
 71             return min(p.distance(s),p.distance(e));
 72         return dispointtoline(p);
 73     }
 74 };
 75 
 76 struct seg{
 77     int l,r,h;
 78     int flag;
 79     seg(){}
 80     seg(int _l,int _r,int _h,int _flag){
 81         l=_l,r=_r,h=_h,flag=_flag;
 82     }
 83     bool operator<(const seg &b)const{
 84         if(k%2==0) return h<b.h;
 85         return h>b.h;
 86     }
 87 }s[maxn];
 88 
 89 void push_down(int rt){
 90     if(lazy[rt]){
 91         lazy[rt<<1]=lazy[rt];
 92         lazy[rt<<1|1]=lazy[rt];
 93         tree[rt<<1]=lazy[rt];
 94         tree[rt<<1|1]=lazy[rt];
 95         lazy[rt]=0;
 96     }
 97 }
 98 
 99 void build(int l,int r,int rt){
100     tree[rt]=0,lazy[rt]=0;
101     if(l==r) return;
102     int mid=l+r>>1;
103     build(lson);
104     build(rson);
105 }
106 
107 void add(int L,int R,int v,int l,int r,int rt){
108     if(L<=l&&R>=r){
109         lazy[rt]=v;
110         tree[rt]=v;
111         return;
112     }
113     push_down(rt);
114     int mid=l+r>>1;
115     if(L<=mid) add(L,R,v,lson);
116     if(R>mid) add(L,R,v,rson);
117 }
118 
119 int query(int L,int l,int r,int rt){
120     if(l==r){
121         return tree[rt];
122     }
123     push_down(rt);
124     int mid=l+r>>1;
125     if(L<=mid) return query(L,lson);
126     return query(L,rson);
127 }
128 
129 int getid(int x){
130     return lower_bound(ve[k/2].begin(),ve[k/2].end(),x)-ve[k/2].begin()+1;
131 }
132 
133 int x[maxn],y[maxn];
134 int xx1[maxn],xx2[maxn],yy1[maxn],yy2[maxn];
135 
136 struct Node{
137     int wall_id;
138     double dist;
139 }bird[maxn];
140 
141 int ans[maxn];
142 
143 int main(){
144     int n,m;
145     while(~scanf("%d %d",&n,&m)){
146         ve[0].clear();
147         ve[1].clear();
148         for(int i=1;i<=n;i++){
149             ans[i]=0;
150             scanf("%d %d %d %d",&xx1[i],&yy1[i],&xx2[i],&yy2[i]);
151             ve[0].pb(xx1[i]),ve[0].pb(xx2[i]);
152             ve[1].pb(yy1[i]),ve[1].pb(yy2[i]);
153             s[i]=seg(xx1[i],xx2[i],yy1[i],i);
154             s[i+n]=seg(xx1[i],xx2[i],yy2[i],i);
155             s[i+n+n+m]=seg(yy1[i],yy2[i],xx1[i],i);
156             s[i+n+n+n+m]=seg(yy1[i],yy2[i],xx2[i],i);
157         }
158         for(int i=1;i<=m;i++){
159             bird[i].dist=1e99;
160             bird[i].wall_id=0;
161             scanf("%d %d",&x[i],&y[i]);
162             ve[0].pb(x[i]);
163             ve[1].pb(y[i]);
164             s[i+n+n]=seg(x[i],x[i],y[i],n+i);
165             s[i+n+n+n+n+m]=seg(y[i],y[i],x[i],n+i);
166         }
167         int pos=1;
168         for(k=0;k<4;k++){
169             sort(ve[k/2].begin(),ve[k/2].end());
170             ve[k/2].erase(unique(ve[k/2].begin(),ve[k/2].end()),ve[k/2].end());
171             sort(s+pos,s+pos+n+n+m);
172             int N=ve[k/2].size();
173             build(1,N,1);
174             int pre=0;
175             int id;
176             for(int i=pos;i<pos+n+n+m;i++){
177                 int L=getid(s[i].l);
178                 int R=getid(s[i].r);
179                 if(L>R) swap(L,R);
180                 if(s[i].flag<=n){
181                     add(L,R,s[i].flag,1,N,1);
182                 }
183                 else{
184                     id=query(L,1,N,1);
185 
186                     if(id!=0){
187                         double dist=Line(Point(xx1[id],yy1[id]),Point(xx2[id],yy2[id])).dispointtoseg(Point(x[s[i].flag-n],y[s[i].flag-n]));
188                         if(sgn(bird[s[i].flag-n].dist-dist)>0){
189                             bird[s[i].flag-n].dist=dist;
190                             bird[s[i].flag-n].wall_id=id;
191                         }
192                     }
193                 }
194             }
195             if(k==1){
196                 pos+=n+n+m;
197             }
198         }
199         for(int i=1;i<=m;i++){
200             ans[bird[i].wall_id]++;
201         }
202         for(int i=1;i<=n;i++){
203             printf("%d\n",ans[i]);
204         }
205     }
206 }
View Code

猜你喜欢

转载自www.cnblogs.com/Fighting-sh/p/10848957.html