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 x1, y1, x2, y2, 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 ",ans[i]); 204 } 205 } 206 }