POJ 3470 Walls(线段树+扫描线)
【题目链接】 http://poj.org/problem?id=3470
【题目大意】
给出几面墙,均垂直于x轴或者y轴,给出一些鸟的位置(二维坐标点),
鸟只会垂直x轴或者y轴飞行,并且会撞上最近的墙,问每面墙最后会有几只鸟撞上去。
【题解】
我们将所有的二维坐标离散,对xy方向分别进行扫描线,
以y轴方向为例,我们先从y最小的线开始扫,
如果是墙,那么在线段树中更新其在x轴上的分布位置
如果是鸟的坐标,那么在线段树中查找其位置,更新其答案。
之后从y最大的开始反向扫描,更新,x方向也同理。
【代码】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <cstdio> #include <algorithm> #include <cstring> #include <climits> using namespace std; const int N=50010; int n,m,wall,tot,dis[N],v[N],w[N],T[10*N],*arr; int x[3*N],y[3*N],ry[3*N],rx[3*N],r[3*N],xs[3*N],ys[3*N],px[3*N],py[3*N]; bool cmp( int a, int b){ return arr[a]<arr[b];} void compress( int *x, int *r, int n, int *a, int *mp){ for ( int i=0;i<n;i++)r[i]=i; arr=x; sort(r,r+n,cmp); int m=-1; a[r[0]]=++m; mp[m]=x[r[0]]; for ( int i=1;i<n;i++){ int cur=r[i],lst=r[i-1]; if (x[cur]==x[lst])a[cur]=m; else a[cur]=++m,mp[m]=x[cur]; } } int query( int q, int x, int l, int r){ if (T[x]!=-2) return T[x]; int mid=(l+r)>>1; if (q<mid) return query(q,x<<1|1,l,mid); return query(q,x+1<<1,mid,r); } void update( int a, int b, int x, int l, int r, int val){ if (r<=a||b<=l) return ; else if (a<=l&&r<=b)T[x]=val; else { if (T[x]!=-2){ T[x+1<<1]=T[x<<1|1]=T[x]; T[x]=-2; } int mid=(l+r)>>1; update(a,b,x<<1|1,l,mid,val); update(a,b,x+1<<1,mid,r,val); } } void scan( int k, int *ys, int *xs, int *py, int W){ if (k<wall){ int _k=k^1; if (xs[_k]>=xs[k])update(xs[k],xs[_k]+1,0,0,W,k/2); } else { int t=query(xs[k],0,0,W); if (~t){ int d=min( abs (py[ys[k]]-py[ys[t*2]]), abs (py[ys[k]]-py[ys[t*2+1]])); k-=wall; if (d<dis[k])dis[k]=d,v[k]=t; } } } void fly( int *ry, int *ys, int *xs, int *py, int W){ T[0]=-1; for ( int i=0;i<tot;i++)scan(ry[i],ys,xs,py,W); T[0]=-1; for ( int i=tot-1;i>=0;i--)scan(ry[i],ys,xs,py,W); } int main(){ scanf ( "%d%d" ,&n,&m); wall=2*n; tot=wall+m; for ( int i=0;i<tot;i++) scanf ( "%d%d" ,x+i,y+i); compress(x,rx,tot,xs,px); compress(y,ry,tot,ys,py); fill(dis,dis+m,INT_MAX); memset (w,0,n); fly(ry,ys,xs,py,xs[rx[tot-1]]+1); fly(rx,xs,ys,px,ys[ry[tot-1]]+1); for ( int i=0;i<m;i++)++w[v[i]]; for ( int i=0;i<n;i++) printf ( "%d\n" ,w[i]); return 0; } |
愿你出走半生,归来仍是少年
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2014-01-23 HDU 2844 Coins