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 }

你可能感兴趣的:(HDU)