题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4666
题意:两种操作:(1)增加一个点到序列中;(2)删除序列中的某个点。在每次操作之后,输出序列中曼哈顿距离最远的两个点之间的距离。点最大为5维。
思路:我们先看二维空间的点,设两个点为(x1,y1),(x2,y2),那么曼哈顿距离为|x1-x2|+|y1-y2|,现在我们去掉绝对值,那么有四种情况:
(x1-x2)+(y1-y2) (x2-x1)+(y1-y2) (x1-x2)+(y2-y1) (x2-x1)+(y2-y1)
由于这四个式子中绝对值均小于等于|x1-x2|+|y1-y2|,而最大的等于|x1-x2|+|y1-y2|,因此我们只要求这四个式子的绝对值的最大值即可。这四个式子进一步变形得到:(x1+y1)-(x2+y2),(-x1+y1)-(-x2+y2),(x1-y1)-(x2-y2),(-x1-y1)-(-x2-y2)。也就是我们我们可以保存四种情况的下每个点的最大值最小值,每种情况的最大最小值之差就是这种情况下的答案,四种情况下的最大值就是答案。
对于这道题,最大5维,也就是最多2^5种情况,用2^5*2(最大值最小值)个堆保存即可。
struct node
{
int p[N],q[N],a[N],size;
void init()
{
size=0;
}
void pushUp(int t)
{
while(1)
{
if(t/2>=1&&a[t/2]<a[t])
{
swap(a[t],a[t/2]);
swap(q[t],q[t/2]);
p[q[t]]=t;
p[q[t/2]]=t/2;
t=t/2;
}
else break;
}
}
void pushDown(int t)
{
int x;
while(1)
{
if(t*2<=size&&a[t*2]>a[t]) x=t*2;
else x=t;
if(t*2+1<=size&&a[t*2+1]>a[x]) x=t*2+1;
if(x==t) break;
swap(a[t],a[x]);
swap(q[t],q[x]);
p[q[t]]=t;
p[q[x]]=x;
t=x;
}
}
void insert(int k,int id)
{
a[++size]=k;
q[size]=id;
p[id]=size;
pushUp(size);
}
void del(int id)
{
if(size==1)
{
size=0;
return;
}
int x=p[id];
a[x]=a[size];
q[x]=q[size--];
p[q[x]]=x;
pushUp(x);
pushDown(x);
}
int top()
{
if(size==0) return 0;
return a[1];
}
};
node a[32][2];
int n,m;
void insert(int p[],int id)
{
int sum,i,j;
FOR0(i,(1<<m))
{
sum=0;
FOR0(j,m)
{
if(i&(1<<j)) sum+=p[j];
else sum-=p[j];
}
a[i][0].insert(sum,id);
a[i][1].insert(-sum,id);
}
}
void del(int id)
{
int i;
FOR0(i,(1<<m))
{
a[i][0].del(id);
a[i][1].del(id);
}
}
int query()
{
int ans=0,i;
FOR0(i,(1<<m)) upMax(ans,a[i][0].top()+a[i][1].top());
return ans;
}
int main()
{
Rush(n)
{
RD(m);
int i,j;
FOR0(i,(1<<m)) a[i][0].init(),a[i][1].init();
int op,p[5];
FOR1(i,n)
{
RD(op);
if(op==0)
{
FOR0(j,m) RD(p[j]);
insert(p,i);
}
else
{
RD(p[0]); del(p[0]);
}
PR(query());
}
}
}