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