link:http://acm.hdu.edu.cn/showproblem.php?pid=4666
这题学会了怎么处理曼哈顿距离。
比如维数是k,那么每个点有2^k个状态,求出在每个状态下,所有点的最大值,最小值,求他们的差,从中找到最大值就行。
开始觉得不好处理的是,删除的时候怎么办。比如要删除一个点,我可以在2^k个中的每个状态里面先找到这个点在这个状态下的值,删除这个值就行了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <cctype> 7 #include <algorithm> 8 #include <queue> 9 #include <deque> 10 #include <queue> 11 #include <list> 12 #include <map> 13 #include <set> 14 #include <vector> 15 #include <utility> 16 #include <functional> 17 #include <fstream> 18 #include <iomanip> 19 #include <sstream> 20 #include <numeric> 21 #include <cassert> 22 #include <ctime> 23 #include <iterator> 24 const int INF = 0x3f3f3f3f; 25 const int dir[8][2] = {{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}}; 26 using namespace std; 27 multiset<int> a[44]; 28 int sad[66666][10],will[66666][44]; 29 int main(void) 30 { 31 #ifndef ONLINE_JUDGE 32 freopen("in.txt","r",stdin); 33 #endif // ONLINE_JUDGE 34 int q,k; 35 while (~scanf("%d%d",&q,&k)) 36 { 37 int apple=1<<k; 38 for(int i=0;i<44;++i) a[i].clear(); 39 for(int i=0;i<q;++i) 40 { 41 int op; scanf("%d",&op); 42 if(op==0) 43 { 44 for(int j=0;j<k;++j) 45 { 46 scanf("%d",&sad[i][j]); 47 } 48 for(int j=0;j<apple;++j) 49 { 50 int s=0; 51 for(int pear=0;pear<k;++pear) 52 { 53 if(j&(1<<pear)) s+=sad[i][pear]; 54 else s-=sad[i][pear]; 55 } 56 will[i][j]=s; 57 a[j].insert(s); 58 } 59 } 60 else 61 { 62 int nu; scanf("%d",&nu); 63 for(int j=0;j<apple;++j) 64 { 65 multiset<int>::iterator it; 66 it=a[j].find(will[nu-1][j]); 67 if(it!=a[j].end()) 68 a[j].erase(it); 69 } 70 } 71 int ans=0; 72 for(int j=0;j<apple;++j) 73 { 74 if(a[j].size()>1) 75 { 76 int big=*(--a[j].end()), 77 small=*(a[j].begin()); 78 // printf("big=%d small=%d\n",big,small); 79 if(big-small>ans) ans=big-small; 80 } 81 } 82 printf("%d\n",ans); 83 } 84 } 85 return 0; 86 }
o(╯□╰)o