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;
}

 

posted @ 2013-09-19 11:33  baoff  阅读(254)  评论(0编辑  收藏  举报