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题意:给定一些操作(0代表添加一个点,1代表删除一个点),求这些点的最远曼哈顿距离以二维平面为例:
设距离最远的两点为 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。
那么要表示一个维数为 dem 的所有状态,只需要用 0 ~ (2^dem-1) 的所有二进制就可以了。
于是只要对所有的点 (xi,yi),依次计算出 (xi+yi), (xi-yi), (-xi+yi), (-xi-yi)这四种形式,然后把每个点i算出来的这四种情况的最大值、最小值分别记录(更新)到数组 max[] 和 min[] 中,然后枚举每一种去绝对值的组合,组合后的最大值即为 answer。
要用到多集合容器(multiset);一个集合(set)是一个容器,它其中所包含的元素的值是唯一的。集和多集的区别是:set支持唯一键值,set中的值都是特定的,而且只出现一次;而multiset中可以出现副本键,同一值可以出现多次。例如: mst[j].insert(sum); 插入一个元素; 则这个元素在容器可能有多个,不是唯一的。所以像set那样,一个值对应一个健值是不行星的,所以往往要多个健值来映射元素, 所以有 j和一个指向该元素的迭代器,这两个健值来映射这个元素sum.另外几个函数功能。begin() 返回指向第一个元素的 迭代器end() 返回指向最后一个元素之后的 迭代器,不是最后一个元素 (要减1,才是指到最后一个元素)clear() 清除所有元素erase() 删除集合中的元素find() 返回一个指向被查找到元素的 迭代器insert() 在集合中插入元素#include<iostream> #include<cstdio> #include<cstring> #include<set>
using namespace std;
const int N=60010; const double INF=1e20;
int n,m,num[N][10]; //map<int,int,greater<int> > mp[1<<5]; multiset<int> mst[1<<5]; multiset<int>::iterator it1,it2; //定义迭代器,它是一个地址
int main(){
//freopen("input.txt","r",stdin);
while(~scanf("%d%d",&n,&m)){ for(int i=0;i<(1<<5);i++) mst[i].clear(); //清空容器 int od,x; for(int i=1;i<=n;i++){ scanf("%d",&od); if(od==0){ for(int j=0;j<m;j++) scanf("%d",&num[i][j]); for(int j=0;j<(1<<m);j++){ //枚举每个点,组成的值。 int sum=0; for(int k=0;k<m;k++){ if(j&(1<<k)) sum+=num[i][k]; else sum-=num[i][k]; } mst[j].insert(sum); //加入到容器中 } }else{ scanf("%d",&x); for(int j=0;j<(1<<m);j++){ //算出要删除的点的sum值。 int sum=0; for(int k=0;k<m;k++){ if(j&(1<<k)) sum+=num[x][k]; else sum-=num[x][k]; } it1=mst[j].find(sum); //在容器中找出这个值对应的迭代器 mst[j].erase(it1); //删除这个迭代器指向的元素 } } int ans=0; //map<int,int>::iterator it1,it2; for(int j=0;j<(1<<m);j++){ it1=mst[j].end(); //最后一个元素的迭代器,要减一 it1--; it2=mst[j].begin(); //第一个元素的迭代器 ans=max(ans,(*it1)-(*it2)); //是地址,注意加*。 } printf("%d\n",ans); } } return 0; }