HDU 4666 Hyperspace 解题报告

题目

题意:

k维平面上,会有一些点出现或者消失,求每次现存的点中,曼哈顿距离最大值。

题解:

以二维为例,对于原点而言,点(x,y)到它的曼哈顿距离为abs(x+y)或abs(x-y),到(x1,y1)的距离为abs(x+y)-abs(x1+y1)或abs(x-y)-abs(x1-y1).所以只要存下当前所有点相对原点的曼哈顿距离,对于每个点,可以用上述的方法查询其它点到它的最大曼哈顿距离。

记下每个点插入时它的最大曼哈顿距离,查询时检测是否还能取到。


//Time:5828MS
//Memory:23108K
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#define MAXN 60010
#define MP(x,y) make_pair(x,y)
#define FI first
#define SE second
using namespace std;
struct _node
{
    int p[5],k,to[32],top;
    void dfs(int h,int sum)
    {
        if(h==k)    to[top++]=sum;
        else    dfs(h+1,sum+p[h]),dfs(h+1,sum-p[h]);
    }
}no[MAXN];
multiset<int> mse[32];
set<pair<int,int> >se;
bool vi[MAXN];
int cal(int h)
{
    if(mse[0].size()==0||!vi[h])    return 0;
    int ret=0;
    for(int i=0,j=1<<no[h].k;i<j;++i)
        ret=max(ret,*(mse[i].rbegin())-no[h].to[i]);
    return ret;
}
void add(int h)
{
    for(int i=0,j=1<<no[h].k;i<j;++i)
        mse[i].insert(no[h].to[i]);
}
void erase(int h)
{
    for(int i=0,j=1<<no[h].k;i<j;++i)
        mse[i].erase(mse[i].find(no[h].to[i]));
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    int n,k,ans,tmp;
    while(scanf("%d%d",&n,&k)==2)
    {
        memset(vi,0,sizeof(vi));
        se.clear();
        for(int i=0,j=1<<k;i<j;++i) mse[i].clear();
        int od;
        for(int i=0;i<n;++i)
        {
            scanf("%d",&od);
            ans=0;
            if(od==0)
            {
                no[i].k=k;
                for(int j=0;j<k;++j)    scanf("%d",&no[i].p[j]);
                no[i].top=0;
                no[i].dfs(0,0);
                vi[i]=1;
                ans=cal(i);
                add(i);
                if(ans>0)
                    se.insert(MP(ans,i));
                ans=0;
            }
            else
            {
                scanf("%d",&tmp);
                vi[tmp-1]=0;
                multiset<int>::iterator ite;
//                for(ite=mse[0].begin();ite!=mse[0].end();++ite) printf("%d ",*ite);
//                printf("\n");
                erase(tmp-1);
//                for(ite=mse[0].begin();ite!=mse[0].end();++ite) printf("%d ",*ite);
//                printf("\n");
            }
            while(se.size())
            {
                int tt=cal(se.rbegin()->SE);
                if(tt==se.rbegin()->FI)
                    break;
                int tmph=se.rbegin()->SE;
                se.erase(*se.rbegin());
                if(tt>0)    se.insert(MP(tt,tmph));
            }
            if(se.size())   ans=se.rbegin()->FI;
            printf("%d\n",ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值