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;
}
posted @   forever97  阅读(357)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
历史上的今天:
2014-01-23 HDU 2844 Coins
点击右上角即可分享
微信分享提示