hdu 4189 SWERC 2011 C - Cybercrime Donut Investigation

http://acm.hdu.edu.cn/showproblem.php?pid=4189

题意说是一个数据库,有n(n<=100, 000)个甜甜圈,每个甜甜圈有两个属性l,w.  (l,w<10^9)

后面有q个询问,会输入q(q<=50, 000)个罪犯的属性l,w。然后输出每个罪犯与数据库中的资料的最小相似度。相似度是  abs(l1-l2)+abs(w1,w2)。

其实如果把属性看做坐标值的话, 相似度就是两个点的绝对距离。

_____________________________________________________

下面分析,n和q都很大,证明这题不水。。。。 

把问题放到坐标图上,我们看着这些一个个的点来讨论。

首先,图上会出现n个坐标点,然后会出现q个询问,让你找出这n个点中,与他绝对距离最小的值。

这个问题也很难处理,还要讨论询问坐标(qx,qy) 与 那n个点的距离没有出现一个规则让你去排序或者贪心来找。

关键就是 abs里面 是会有正负,距离价值无法定位。

那我们再把问题简化,如果我们假设,出现的(qx,qy) 对于任意一个数据库中的 (xi,yi) 都满足 (qx>=xi,qy>=yi) 。

这样的话我们是不是 这个去找 xi+yi 值 尽可能大的值 来使得 dis=(qx-xi)+(qy-yi)  尽可能的小!

 

上面其实已经把 问题解决了,后面就是代码实现的问题了,我们只需要去 定义四种 规则 

1  (qx>=xi,qy>=yi) 

2  (qx>=xi,qy<=yi) 

3  (qx<=xi,qy>=yi) 

4  (qx<=xi,qy<=yi)

后面寻找使得dis 最小的 值

代码的实现我是把n+q个点放一起排序,

比如第一种情况 :在扫到询问点时,满足 qx>xi, 当qx==xi时 qy>=yi 

但是在之前的点必然会出现 qx>xi&&qx<yi  这些不满足  (qx>=xi,qy>=yi) 的点。

这个用线段树来规划一下范围,然后在规定的范围内进行查找就不会碰到(qx<yi)的点了。

而扫到数据库中的点,就放入线段树更新。

 

其实代码可以只扫两边,但是,为了思路明确(关键是懒得改了),我把四种情况都分别排序建树查询。

复杂度 (n+q)*log(n+q)

附上代码

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 #define N 100010
  8 #define M 260010
  9 typedef long long LL;
 10 struct node{
 11     LL x,y;
 12     int id;
 13 }w[150010];
 14 LL ty[150010],ans[100010];
 15 int ny;
 16 struct Tree{
 17     int l,r;
 18     LL val;
 19 }tree[1050010];
 20 bool cmp1(const node &a,const node &b){
 21     if(a.x!=b.x) return a.x<b.x;
 22     if(a.y!=b.y) return a.y<b.y;
 23     return a.id<b.id;
 24 }
 25 bool cmp2(const node &a,const node &b){
 26     if(a.x!=b.x) return a.x<b.x;
 27     if(a.y!=b.y) return a.y>b.y;
 28     return a.id<b.id;
 29 }
 30 bool cmp3(const node &a,const node &b){
 31     if(a.x!=b.x) return a.x>b.x;
 32     if(a.y!=b.y) return a.y<b.y;
 33     return a.id<b.id;
 34 }
 35 bool cmp4(const node &a,const node &b){
 36     if(a.x!=b.x) return a.x>b.x;
 37     if(a.y!=b.y) return a.y>b.y;
 38     return a.id<b.id;
 39 }
 40 int findy(LL y){
 41     int l=0,r=ny-1;
 42     while(l<=r){
 43         int mid=(l+r)>>1;
 44         if(ty[mid]<y) l=mid+1;
 45         else if(ty[mid]>y) r=mid-1;
 46         else return mid+1;
 47     }
 48 }
 49 void build(int L,int R,int x){
 50     tree[x].l=L;
 51     tree[x].r=R;
 52     tree[x].val=1000000000000;
 53     if(L==R) return ;
 54     int mid=(L+R)>>1;
 55     build(L,mid,x<<1);
 56     build(mid+1,R,x<<1|1);
 57 }
 58 LL find(int L,int R,int x){
 59     if(tree[x].l>=L&&tree[x].r<=R)
 60         return tree[x].val;
 61     
 62     int mid=(tree[x].l+tree[x].r)>>1;
 63     if(R<=mid) return find(L,R,x<<1);
 64     if(L>mid) return find(L,R,x<<1|1);
 65     return min(find(L,mid,x<<1),find(mid+1,R,x<<1|1));
 66 }
 67 void update(int id,int x,LL val){
 68     if(tree[x].l==tree[x].r){
 69         tree[x].val=min(tree[x].val,val);
 70         return ;
 71     }
 72     int mid=(tree[x].l+tree[x].r)>>1;
 73     if(id<=mid) update(id,x<<1,val);
 74     else update(id,x<<1|1,val);
 75     tree[x].val=min(tree[x<<1].val,tree[x<<1|1].val);
 76 }
 77 int main(){
 78     int n,q,cs=0;
 79     while(scanf("%d",&n)&&n!=-1){
 80         if(cs) printf("\n");
 81         else cs=1;
 82         for(int i=0;i<n;++i){
 83             scanf("%lld%lld",&w[i].x,&w[i].y);
 84             w[i].id=-1;
 85             ty[i]=w[i].y;
 86         }
 87         scanf("%d",&q);
 88         for(int i=0;i<q;++i){
 89             ans[i]=1000000000000;
 90             scanf("%lld%lld",&w[i+n].x,&w[i+n].y);
 91             w[i+n].id=i;
 92             ty[i+n]=w[i+n].y;
 93         }
 94         sort(ty,ty+n+q);
 95         ny=0;
 96         for(int i=1;i<n+q;++i)
 97             if(ty[i]!=ty[ny]) ty[++ny]=ty[i];
 98         ny++;
 99 
100 
101         
102         LL my=ty[ny-1],iy=ty[0];
103         //1
104         build(1,ny,1);
105         sort(w,w+n+q,cmp1);
106         LL mx=w[n+q-1].x,ix=w[0].x;
107         for(int i=0;i<n+q;++i){
108             if(w[i].id!=-1){
109                 int j=findy(w[i].y);
110                 ans[w[i].id]=min(ans[w[i].id],find(1,j,1)-(my-w[i].y)-(mx-w[i].x));
111             }
112             else update(findy(w[i].y),1,(my-w[i].y)+(mx-w[i].x));
113         }
114 
115         //2
116         build(1,ny,1);
117         sort(w,w+n+q,cmp2);
118         for(int i=0;i<n+q;++i){
119             if(w[i].id!=-1){
120                 int j=findy(w[i].y);
121                 ans[w[i].id]=min(ans[w[i].id],find(j,ny,1)-(w[i].y-iy)-(mx-w[i].x));
122             }
123             else update(findy(w[i].y),1,(w[i].y-iy)+(mx-w[i].x));
124         }
125 
126         //3
127         build(1,ny,1);
128         sort(w,w+n+q,cmp3);
129         for(int i=0;i<n+q;++i){
130             if(w[i].id!=-1){
131                 int j=findy(w[i].y);
132                 ans[w[i].id]=min(ans[w[i].id],find(1,j,1)-(my-w[i].y)-(w[i].x-ix));
133             }
134             else update(findy(w[i].y),1,(my-w[i].y)+(w[i].x-ix));
135         }
136 
137         //4
138         build(1,ny,1);
139         sort(w,w+n+q,cmp4);
140         for(int i=0;i<n+q;++i){
141             if(w[i].id!=-1){
142                 int j=findy(w[i].y);
143                 ans[w[i].id]=min(ans[w[i].id],find(j,ny,1)-(w[i].y-iy)-(w[i].x-ix));
144             }
145             else update(findy(w[i].y),1,(w[i].y-iy)+(w[i].x-ix));
146         }
147         for(int i=0;i<q;++i) printf("%lld\n",ans[i]);
148     }
149     return 0;
150 }

转载于:https://www.cnblogs.com/slon/archive/2012/03/30/2426104.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值