题目传送门
以二维为例,二维下两点间的曼哈顿距离最大值为(max(|x_i-x_j| + |y_i-y_j|)),可以通过枚举坐标符号正负来去掉绝对值。即(max(x_i-x_j+y_i-y_j,x_i+x_j+y_i-y_j...))共16种情况。设(f[i][t])表示第(i)个点各维度数值正负状态为(t)时的值,假如二维向量(p[i]=(1,2)),那么状态(t)的范围为([0,3]),如果(t=2),即二进制表示为(10),那么(p)向量第一维数值加个负号,第二维数值不变,类似状压过程。对于每个向量处理出(f)的值。最终结果即在([l,r])范围内求(max(f[i][m],f[j][n])(m+n=(1<<k)-1)),具体用线段树实现。
#include<cstdio>
#include<vector>
#include<algorithm>
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int N = 2e5 + 50;
struct Node{
vector<int> val;
Node() { val.resize(35); }
}node[N << 2];
int n, k, q;
int a[N][6];
void Max(const vector<int> &x, const vector<int> &y, vector<int> &z){
for(int i = 0; i < (1 << k); ++i) z[i] = max(x[i], y[i]);
}
void Max(const vector<int> &x, vector<int> &y){
for(int i = 0; i < (1 << k); ++i) y[i] = max(x[i], y[i]);
}
void build(int u, int l, int r){
if(l == r){
for(int s = 0; s < (1 << k); ++s){
for(int t = 1; t <= k; ++t){
if(s & (1 << (t - 1))) node[u].val[s] += a[l][t];
else node[u].val[s] -= a[l][t];
}
}
return ;
}
int mid = (l + r) >> 1;
if(l <= mid) build(ls, l, mid);
if(r > mid) build(rs, mid + 1, r);
Max(node[ls].val, node[rs].val, node[u].val);
}
void modify(int u, int l, int r, int pos){
if(l == r){
for(int i = 0; i < (1 << k); ++i) node[u].val[i] = 0;
for(int s = 0; s < (1 << k); ++s){
for(int t = 1; t <= k; ++t){
if(s & (1 << (t - 1))) node[u].val[s] += a[l][t];
else node[u].val[s] -= a[l][t];
}
}
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid) modify(ls, l, mid, pos);
else modify(rs, mid + 1, r, pos);
Max(node[ls].val, node[rs].val, node[u].val);
}
vector<int> ans(35);
void query(int u, int l, int r, int ql, int qr){
if(ql <= l && qr >= r){
Max(node[u].val, ans);
return ;
}
int mid = (l + r) >> 1;
if(ql <= mid) query(ls, l, mid, ql, qr);
if(qr > mid) query(rs, mid + 1, r, ql, qr);
}
int main(){
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i)
for(int t = 1; t <= k; ++t)
scanf("%d", &a[i][t]);
build(1, 1, n);
scanf("%d", &q);
while(q--){
int opt, id, l, r;
scanf("%d", &opt);
if(opt == 1){
scanf("%d", &id);
for(int i = 1; i <= k; ++i) scanf("%d", &a[id][i]);
modify(1, 1, n, id);
}
else{
for(int i = 0; i < 35; ++i) ans[i] = -1e9;
scanf("%d%d", &l, &r);
query(1, 1, n, l, r);
int maxx = 0;
for(int s = 0; s < (1 << k); ++s){
maxx = max(maxx, ans[s] + ans[(1 << k) - 1 - s]);
}
printf("%d
", maxx);
}
}
}