HDU 4189 数据结构+降二维为一维处理扫一遍(坐标点)+曼哈顿距离+离线处理(比较难想的思路!)
题意说是一个数据库,有n(n<=100, 000)个甜甜圈,每个甜甜圈有两个属性l,w. (l,w<10^9)
后面有q个询问,会输入q(q<=50, 000)个罪犯的属性l,w。然后输出每个罪犯与数据库中的资料的最小相似度。相似度是 abs(l1-l2)+abs(w1,w2)。
其实如果把属性看做坐标值的话, 相似度就是两个点的绝对距离。
思路:
我们只需要去 定义四种 规则
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) 的点。
树状数组搞定:
#include<cstdlib> #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #define LL long long #define inf 0x7ffffffffffffffll #define N 200009 using namespace std; LL k,n,t,m; struct Node { LL x,y,id; bool operator<(const Node &a)const { return x<a.x||(x==a.x&&y<a.y); } } node[N],q[50009]; LL y[N],ny; LL c[N]; LL ans[50009]; void add(int x,LL v) { x+=2; while(x<N) { c[x]=max(c[x],v); x+=x&-x; } } LL sum(int x) { x+=2; LL ans=-inf;//WA是因为inf小了!!! while(x>0) { ans=max(ans,c[x]); x-=x&-x; } return ans; } void fun() { memset(c,0x80,sizeof(c));//////////////////// for(int i=0,j=0; i<m; i++) { for(; j<n; j++) { if(node[j].x<=q[i].x) { int sub=lower_bound(y,y+ny,node[j].y)-y; LL val=node[j].x+node[j].y; add(sub,val); } else break; } int sub=lower_bound(y,y+ny,q[i].y)-y; ans[q[i].id]=min(ans[q[i].id],q[i].x+q[i].y-sum(sub)); } memset(c,0x80,sizeof(c));//////////////////// for(int i=0,j=0; i<m; i++) { for(; j<n; j++) { if(node[j].x<=q[i].x) { int sub=lower_bound(y,y+ny,node[j].y)-y; LL val=node[j].x-node[j].y; add(ny-1-sub,val); } else break; } int sub=lower_bound(y,y+ny,q[i].y)-y; ans[q[i].id]=min(ans[q[i].id],q[i].x-q[i].y-sum(ny-1-sub)); } memset(c,0x80,sizeof(c));//////////////////// for(int i=m-1,j=n-1; i>=0; i--) { for(; j>=0; j--) { if(node[j].x>=q[i].x) { int sub=lower_bound(y,y+ny,node[j].y)-y; LL val=-node[j].x-node[j].y; add(ny-1-sub,val); } else break; } int sub=lower_bound(y,y+ny,q[i].y)-y; ans[q[i].id]=min(ans[q[i].id],-q[i].x-q[i].y-sum(ny-1-sub)); } memset(c,0x80,sizeof(c));//////////////////// for(int i=m-1,j=n-1; i>=0; i--) { for(; j>=0; j--) { if(node[j].x>=q[i].x) { int sub=lower_bound(y,y+ny,node[j].y)-y; LL val=-node[j].x+node[j].y; add(sub,val); } else break; } int sub=lower_bound(y,y+ny,q[i].y)-y; ans[q[i].id]=min(ans[q[i].id],-q[i].x+q[i].y-sum(sub)); } } int main() { #ifndef ONLINE_JUDGE freopen("ex.in","r",stdin); #endif LL f=1; while(scanf("%I64d",&n)==1&&n!=-1) { if(f) f=0; else puts(""); for(int i=0; i<n; i++) { scanf("%I64d%I64d",&node[i].x,&node[i].y); y[i]=node[i].y; } sort(node,node+n); scanf("%I64d",&m); for(int i=0; i<m; i++) { scanf("%I64d%I64d",&q[i].x,&q[i].y); y[i+n]=q[i].y; q[i].id=i; } sort(y,y+n+m); ny=unique(y,y+n+m)-y; sort(q,q+m); memset(ans,0x7f,sizeof(ans)); fun(); for(int i=0; i<m; i++) printf("%I64d\n",ans[i]); } return 0; }