codeforces1093 G Multidimensional Queries

https://codeforces.com/contest/1093/problem/G

题意:

给你n个k维空间上的点,定义两点间距离为他们的曼哈顿距离,有两个操作:
1.把第i个点换成另一个点b
2.查询第i个点到第j个点中距离最远的连个点。

题解:

直接做过类似的题,我们可以把绝对值拆开,拆开之后把同一个点的坐标防在一起。因为k只有5,因此坐标的符号最多只有32种可能,而两个点的距离由于绝对值的关系一定是两个加起来最大的。因此,只需要用线段树来维护区间最值就可以了。因为有32种情况,所以要建立32棵线段树。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int bit[6]={1,2,4,8,16,32};
struct node
{
	int x,id;
	node(){};
	node(int aa,int bb):x(aa),id(bb){}
}tree[maxn<<2][33];
node Max(const node& a,const node& b)
{
	return a.x>b.x?a:b;
}
int a[maxn][10];
void pushup(int rt,int t)
{
	tree[rt][t]=Max(tree[rt<<1][t],tree[rt<<1|1][t]);
}
void update(int C,int l,int r,int L,int rt,int t)
{
	if(l==r)
	{
//		cout<<l<<" "<<rt<<endl;
		tree[rt][t]=node(C,L);
		return;
	}
	int m=(l+r)>>1; 
//	pushdown(l,r,rt);
	if(L<=m) update(C,l,m,L,rt<<1,t);
	else update(C,m+1,r,L,rt<<1|1,t);
	pushup(rt,t);
}
node query(int l,int r,int L,int R,int rt,int t)
{
	if(L<=l&&r<=R)	return tree[rt][t];
	int m=(l+r)>>1;
	node _max=node(-1e9,0);
	if(L<=m) _max=Max(_max,query(l,m,L,R,rt<<1,t));
	if(R>m) _max=Max(_max,query(m+1,r,L,R,rt<<1|1,t));
//	cout<<L<<" "<<R<<" "<<_max<<endl;
	return _max;
}
int n,k;
void build(int l,int r,int rt,int t)
{
	if(l==r)
	{
		int temp=0;
		for(int j=0;j<k;j++)
		{
			if(((t>>j)&1)==1) temp+=a[l][j]*-1;
			else temp+=a[l][j];
		}
		tree[rt][t].id=l;
		tree[rt][t].x=temp;
		return ;
	 } 
	int m=(l+r)/2;
	build(l,m,rt*2,t);
	build(m+1,r,rt*2+1,t);
	pushup(rt,t);
 } 
void change(int N)
{
	int i,j;
	for(i=0;i<bit[k];i++)
	{
		int temp=0;
		for(j=0;j<k;j++)
		{
			if(((i>>j)&1)==1) temp+=a[N][j]*-1;
			else temp+=a[N][j];
		}
		update(temp,1,n,N,1,i);
	}
}
int ret[40];
int Q(int l,int r)
{
	if(l==r) return 0;
	int _max=-1e9;
	for(int i=0;i<bit[k];i++)
	{
//		cout<<query(1,n,l,l,1,i)<<" "<<query(1,n,l+1,r,1,pow(2,k)-1-i)<<endl;
		ret[i]=query(1,n,l,r,1,i).x;
//		if(temp.id>l)	_max=max(query(1,n,l,temp.id-1,1,(bit[k]-1)^i).x+temp.x,_max);
//		if(temp.id<r)	_max=max(query(1,n,temp.id+1,r,1,(bit[k]-1)^i).x+temp.x,_max);
	}
	for(int i=0; i<(1<<k); i++){
		_max = max(_max, abs(ret[i]+ret[i^((1<<k)-1)]));
	}
	return _max;
}
int main()
{  
	#ifdef TEST
		freopen("input.txt","r",stdin);
    #endif
	int T,m,i,j;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++)
		for(j=0;j<k;j++)
			scanf("%d",&a[i][j]);
	for(i=0;i<bit[k];i++) build(1,n,1,i);
	int q,o,N,l,r;
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d",&o);
		if(o==1)
		{
			scanf("%d",&N);
			for(i=0;i<k;i++)scanf("%d",&a[N][i]);
			change(N);
		}
		else
		{
			scanf("%d%d",&l,&r);
			printf("%d\n",Q(l,r));
		}
	}
}


Q.E.D.