和去年多校的CSGO一样,用状态压缩来求Manhattan距离的最大值
然后要用线段树维护一下区间最大值
/* k维空间给定n个点,两个操作 1 i b1 b2 .. bk : 修改第i个点的坐标 2 l r:询问[l,r]区间点最大的曼哈顿距离 先考虑不带修: 线段树维护区间2^5种状态的最大值 查询时只要求出相对的两个状态的最大值即可 关于这个贪心的证明: 首先因为绝对值,所以aij前面带的符号可能是-也可能是+,总共就是有关2^k种可能 那么考虑每种状态 S 的最大值,加上相对这种状态 (1<<k)-S 的最大值,来维护答案 其实会有很多情况是不应该存在的,比如aij是第j维最小的,那么其前面的符号就只能是- 可是当其前面的符号是+时也被考虑进去了,其实能够保证另有一个数比这种情况大 即这种情况对结果不造成影响 再来考虑待修的情况 修改pos位置的点,就要去线段树中更新和这个点有关的2^5种状态 所以还是线段树维护区间最大值的问题,可以用一个结点来维护 */ #include<bits/stdc++.h> using namespace std; #define maxn 200005 int k,n,m,a[maxn][10],v[maxn][1<<5]; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct Node{int Max,val[1<<5];}p[maxn<<2]; void pushup(int rt){ for(int i=0;i<(1<<5);i++) p[rt].val[i]=max(p[rt<<1].val[i],p[rt<<1|1].val[i]); p[rt].Max=-0x3f3f3f3f; for(int i=0;i<(1<<5);i++) p[rt].Max=max(p[rt].Max,p[rt].val[i]+p[rt].val[(1<<5)-1-i]); } void build(int l,int r,int rt){ if(l==r){ for(int i=0;i<(1<<5);i++){ p[rt].val[i]=v[l][i]; // p[rt].Max=max(p[rt].Max,v[l][i]); } return; } int m=l+r>>1; build(lson);build(rson); pushup(rt); } void update(int pos,int l,int r,int rt){//更新第pos个点 if(l==r){ for(int i=0;i<(1<<5);i++) p[rt].val[i]=v[l][i]; return; } int m=l+r>>1; if(pos<=m)update(pos,lson); else update(pos,rson); pushup(rt); } Node merge(Node a,Node b){ for(int i=0;i<(1<<5);i++) a.val[i]=max(a.val[i],b.val[i]); for(int i=0;i<(1<<5);i++) a.Max=max(a.Max,a.val[i]+b.val[(1<<5)-i-1]); return a; } Node query(int L,int R,int l,int r,int rt){ if(L<=l && R>=r) return p[rt]; int m=l+r>>1; Node res; for(int i=0;i<(1<<5);i++) res.val[i]=-0x3f3f3f3f; res.Max=-0x3f3f3f3f; if(L<=m) res=merge(res,query(L,R,lson)); if(R>m) res=merge(res,query(L,R,rson)); return res; } int main(){ cin>>n>>k; for(int i=1;i<=n;i++){ for(int j=0;j<k;j++) scanf("%d",&a[i][j]); for(int S=0;S<(1<<5);S++){ for(int j=0;j<5;j++) if(S&(1<<j))v[i][S]+=a[i][j]; else v[i][S]-=a[i][j]; } } build(1,n,1); cin>>m; int op,l,r,pos; while(m--){ scanf("%d",&op); if(op==1){ scanf("%d",&pos); for(int i=0;i<k;i++) scanf("%d",&a[pos][i]); for(int S=0;S<(1<<5);S++){ v[pos][S]=0; for(int j=0;j<5;j++) if(S&(1<<j)) v[pos][S]+=a[pos][j]; else v[pos][S]-=a[pos][j]; } update(pos,1,n,1); } else { scanf("%d%d",&l,&r); Node node=query(l,r,1,n,1); cout<<node.Max<<' '; } } }