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

求m维最远曼哈顿距离

借鉴别人的思路http://www.cnblogs.com/jackge/archive/2013/08/14/3256402.html

以二维平面为例:

设距离最远的两点为 i, j,可知所求的最大距离必定有以下四种形式之一:

(xi-xj)+(yi-yj), (xj-xi)+(yi-yj), (xi-xj)+(yj-yi), (xj-xi)+(yj-yi) 变形一下,把相同点的坐标放到一起,

即 (xi+yi)-(xj+yj), (-xi+yi)-(-xj+yj), (xi-yi)-(xj-yj), (-xi-yi)-(-xj-yj),可以发现即去绝对值之后把同一点的坐标放在一起,对应坐标符号相同。

假如我们用0表示符号,用1表示正号,那么 (xi+yi) 可以表示为 11。

 

由于在线并且有删除操作,最大最小值我们分别用两个堆来维护,枚举所有状态找出最大值即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <set>

using namespace std;

struct node1{
    int v,num;
    friend bool operator <(node1 a,node1 b){
        return a.v<b.v;
    }
};

struct node2{
    int v,num;
    friend bool operator <(node2 a,node2 b){
        return a.v>b.v;
    }    
};

int vis[60006];

int main(){
    int q,m;
    while(~scanf("%d%d",&q,&m)){
        priority_queue <node1> h1[1<<5];
        priority_queue <node2> h2[1<<5];
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=q;i++){
            int op;
            scanf("%d",&op);
            int a[6];
            if(!op){
                for(int j=0;j<m;j++)
                    scanf("%d",&a[j]);
                for(int j=0;j<(1<<m);j++){
                    int cnt=0;
                    for(int k=0;k<m;k++){
                        if(j&(1<<k)){
                            cnt+=a[k];
                        }
                        else{
                            cnt-=a[k];
                        }
                    }
                    node1 p1;
                    node2 p2;
                    p1.v=p2.v=cnt;
                    p1.num=i;p2.num=i;
                    h1[j].push(p1);
                    h2[j].push(p2);
                }
            }
            else{
                int x;
                scanf("%d",&x);
                vis[x]=1;
            }
            int ans=0;
            for(int j=0;j<(1<<m);j++){
                node1 cnt1;
                node2 cnt2;
                int flag=0;
                while(!h1[j].empty()){
                    cnt1=h1[j].top();
                    if(!vis[cnt1.num]){
                        flag++;
                        break;
                    }
                    h1[j].pop();
                }
                while(!h2[j].empty()){
                    cnt2=h2[j].top();
                    if(!vis[cnt2.num]){
                        flag++;
                        break;
                    }
                    h2[j].pop();
                }
                if(flag==2)ans=max(ans,cnt1.v-cnt2.v);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code