http://acm.hdu.edu.cn/showproblem.php?pid=4666
Hyperspace
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 615 Accepted Submission(s): 280
However, the device is in test phase, often in a unstable state. Mr.Smith worried that it may cause an explosion while testing it. The energy of the device is related to the maximum manhattan distance among particle.
Particles may appear and disappear any time. Mr.Smith wants to know the maxmium manhattan distance among particles when particle appears or disappears.
In each case: In the first line, there are two integer q(number of particle appear and disappear event, ≤60000) and k(dimensions of the hyperspace that the hyperspace the device generated, ≤5). Then follows q lines. In each line, the first integer ‘od’ represents the event: od = 0 means this is an appear
event. Then follows k integer(with absolute value less then 4 × 107). od = 1 means this is an disappear event. Follows a integer p represents the disappeared particle appeared in the pth event.
思路:这道题比赛时候是队友过的,赛后看了题解才明白过来。
详细的思路可以参考:09年集训队论文:《浅谈信息学竞赛中的“0”和“1”》
对于这道题,我们可以先从低维开始讨论,看看可以得出什么结论,
首先是一维的情况,显然我们只需维护一维空间点的最大值和最小值,然后相减即为所求答案,但这并没有对我们解决原题有太大帮助。
然后考虑二维的情况,对于二维空间中的两点A(x1,y1),B(x2,y2),它们的曼哈顿距离即为 |x1-x2|+|y1-y2|。
我们容易得出下面的结论:
|x1-x2|+|y1-y2|= MAX{ (x1-x2)+(y1-y2),(x1-x2)-(y1-y2),-(x1-x2)+(y1-y2),-(x1-x2)-(y1-y2) }
等价于|x1-x2|+|y1-y2|=MAX{ (x1+y1)-(x2+y2),(x1-y1)-(x2-y2),(-x1+y1)-(-x2+y2),(-x1-y1)-(-x2-y2)};
对于第二个式子,我们可以枚举二维空间中点的X轴和Y轴座标前的正负号,有2^2=4种可能,用0到3表示,我们不妨设1为正,0为负,则2(10)则表示x-y,1(01)表示 -x+y等等。。。我们可以用四个数据结构维护四种可能的点的最大值和最小值,然后做差取较大值即为答案。事实上,对于多维的情况我们也可以采用类似的方法做,只不过需要2^k种可能。题目中k最大为5,所以最多有32种情况。维护最大值和最小之可以用set,堆等等,考虑到还需要删除点,为了方便,我的代码中用的是 multiset,其实set和堆也是可行的。
参考代码如下:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <set>
using namespace std;
multiset<int> ms[1<<5];
multiset<int>::iterator itor;
int a[60010][5];
int main()
{
//freopen("dd.txt","r",stdin);
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
int i;
for(i=0;i<32;i++)
ms[i].clear();
for(i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
if(t==0)
{
for(int j=0;j<k;j++)
scanf("%d",&a[i][j]);
for(int j=0;j<1<<k;j++)
{
int sum=0;
for(int tt=0;tt<k;tt++)
{
if(1&(j>>tt))
sum+=a[i][tt];
else
sum-=a[i][tt];
}
ms[j].insert(sum);
}
}
else
{
int x;
scanf("%d",&x);
for(int j=0;j<(1<<k);j++)
{
int sum=0;
for(int tt=0;tt<k;tt++)
{
if(1&(j>>tt))
sum+=a[x][tt];
else
sum-=a[x][tt];
}
itor=ms[j].find(sum);
ms[j].erase(itor);
}
}
int ans=0;
for(int j=0;j<(1<<k);j++)
{
itor=ms[j].end();
itor--;
int t1=(*itor);
itor=ms[j].begin();
int t2=(*itor);
ans=max(ans,t1-t2);
}
printf("%d\n",ans);
}
}
return 0;
}