10 2 0 208 403 0 371 -180 1 2 0 1069 -192 0 418 -525 1 5 1 1 0 2754 635 0 -2491 961 0 2954 -2516
0 746 0 1456 1456 1456 0 2512 5571 8922
思路:
先求曼哈顿距离(复杂度:O(n*k*2^k) k-维数 ),例如二维的曼哈顿距离,有两点(x1,y1),(x2,y2),那么它们的曼哈顿距离就是 dist=|x1-x2|+|y1-y2|,去绝对值得
dist=max( x2+y2-(x1+y1) , (x2-y2)-(x1-y1) , (-x2+y2)-(-x1+y1) , (-x2-y2)-(-x1-y1) );
可以看出每个式子中的两点的符号都是一样的,那么问题就简化为
找到每个符号状态下的最大最小值相减取最大值就够了。
扩展到多维是一样的,求曼哈顿距离解决了,然后用二进制来枚举状态,用multiset来维护插入删除就够了。
注意:
multiset中对值删除的话是删除所有的这些值,所以要找到一个指针后再删除。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 35 #define MAXN 60005 #define mod 100000007 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 typedef long long ll; using namespace std; int n,m,w,ans; bool vis[MAXN]; int x[MAXN][5]; multiset<int>dist[maxn]; multiset<int>::iterator it; int main() { int i,j,k,t,op,d; while(~scanf("%d%d",&n,&w)) { m=1<<w; for(i=0; i<m; i++) { dist[i].clear(); } memset(vis,0,sizeof(vis)); for(i=1; i<=n; i++) { scanf("%d",&op); if(!op) { for(j=0; j<w; j++) { scanf("%d",&x[i][j]); } for(j=0; j<m; j++) { d=0; for(k=0; k<w; k++) { if(j&(1<<k)) d+=x[i][k]; else d-=x[i][k]; } dist[j].insert(d); } ans=0; for(j=0; j<m; j++) { if(!dist[j].empty()) { it=dist[j].end(); it--; ans=max(ans,*it-*dist[j].begin()); } } } else { scanf("%d",&t); if(!vis[t]) { vis[t]=1; for(j=0; j<m; j++) { d=0; for(k=0; k<w; k++) { if(j&(1<<k)) d+=x[t][k]; else d-=x[t][k]; } it=dist[j].find(d); dist[j].erase(it); } } ans=0; for(j=0; j<m; j++) { if(!dist[j].empty()) { it=dist[j].end(); it--; ans=max(ans,*it-*dist[j].begin()); } } } printf("%d\n",ans); } } return 0; }