CF1093G Multidimensional Queries

简要题面:有 \(n\)\(k\) 维点,求区间任意 \(2\) 点曼哈顿距离最大值,带修
考虑拆曼哈顿距离的绝对值,即\(\sum ^{k}_{i=1}\limits |a_i-b_i|\)
显然在每个维度上,任意两点的值要么是正数要么是负数,\(k\) 大小只有 \(5\)
也就是说,对于每个点每个维度上正负的枚举,最多有\(2^k\)\(32\)种可能
我们就可以去用二进制去表示每个点每一维度的正负
再次考虑式子,我们拆开后\(2\)个点的每个维度值必然一个相较于原来是相反的,另一个则相同,体现到二进制上则是每一维度\(01\)互相对应,这时我们答案即为\(max\{f[0]+f[31],f[1]+f[30],....\}(00000+11111,00001+11110,....)\)
维护:

点击查看代码
void pu(int p){
	for(int i=0;i<(1<<k);i++){
		t[p].val.f[i]=max(t[ls].val.f[i],t[rs].val.f[i]);
	}
}

带修也很简单,线段树直接维护即可
(不知道为什么static int会有奇怪的问题,调了 \(2\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct sz{
	int f[35];
};
struct node{
	int l,r;sz val;
}t[N<<2];
int n,m,k,point[N][10];
#define ls p*2
#define rs p*2+1
#define mid (t[p].l+t[p].r)/2
void pu(int p){
	for(int i=0;i<(1<<k);i++){
		t[p].val.f[i]=max(t[ls].val.f[i],t[rs].val.f[i]);
	}
}
void build(int p,int l,int r){
	t[p].l=l;t[p].r=r;
	if(l==r){
		for(int i=0;i<k;i++)scanf("%d",&point[l][i]);
		for(int i=0;i<(1<<k);i++){
			t[p].val.f[i]=0;
			for(int j=0;j<k;j++){
				if(i&(1<<j))t[p].val.f[i]+=point[l][j];
				else t[p].val.f[i]-=point[l][j];
			}
		}
		return ;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pu(p);
}
void upd(int p,int pos){
	if(t[p].l==t[p].r){
		for(int i=0;i<k;i++)scanf("%d",&point[pos][i]);
		for(int i=0;i<(1<<k);i++){
			t[p].val.f[i]=0;
			for(int j=0;j<k;j++){
				if(i&(1<<j))t[p].val.f[i]+=point[pos][j];
				else t[p].val.f[i]-=point[pos][j];
			}
		}
		return ;
	}
	if(pos<=mid)upd(ls,pos);
	else upd(rs,pos);
	pu(p);
}
sz query(int p,int l,int r){
	if(l==t[p].l&&r==t[p].r){
		return t[p].val;
	}
	if(r<=mid)return query(ls,l,r);
	else if(l>mid)return query(rs,l,r);
	else{
		sz lson=query(ls,l,mid),rson=query(rs,mid+1,r);
		sz tmp;
		for(int i=0;i<(1<<k);i++){
			tmp.f[i]=max(lson.f[i],rson.f[i]);
		}
		return tmp;
	}
}
#undef ls
#undef rs
#undef mid
int main(){
	scanf("%d%d",&n,&k);
	build(1,1,n);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			int pos;
			scanf("%d",&pos);
			upd(1,pos);
		}
		else{
			int l,r,tmp=0;
			scanf("%d%d",&l,&r);
			auto ans=query(1,l,r);
			for(int i=0;i<(1<<(k-1));i++){
				tmp=max(tmp,ans.f[i]+ans.f[(1<<k)-1-i]);
			}
			printf("%d\n",tmp);
		}
	}
	return 0; 
} 
posted @ 2023-05-17 23:26  Linnyx  阅读(19)  评论(0编辑  收藏  举报