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;
}