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.