给出一个 n n n个 k k k元组 ( k ≤ 5 ) (k \le 5) (k≤5),支持两种操作:
转换为 k k k维空间问题。
两两之间的曼哈顿距离最大值就是将带绝对值的曼哈顿距离符号拆开所有情况中的最大值。
所以将此看成一个 k k k维曼哈顿距离,就可以将其状压了。
状压之后维护一个线段树即可。
/*** keep hungry and calm CoolGuang! ***/
//#pragma GCC optimize(3)
#include
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const int maxn = 1e6+700;
const int mod= 998244353;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll sum[maxn][40];
ll mx[maxn];
ll a[maxn][5];
int MAX;
void push(int k,int l,int r){
mx[k] = max(mx[k<<1],mx[k<<1|1]);
for(int i=0;i<MAX;i++)
mx[k] = max(mx[k],max(sum[k<<1][i]+sum[k<<1|1][(MAX-1)^i],sum[k<<1|1][i]+sum[k<<1][(MAX-1)^i]));
for(int i=0;i<MAX;i++) sum[k][i] = max(sum[k<<1][i],sum[k<<1|1][i]);
//printf("%d->[%d %d] = %lld\n",k,l,r,mx[k]);
}
void build(int k,int l,int r){
if(l == r){
for(int i=0;i<MAX;i++){
ll tmp = 0;
for(int j=0;j<m;j++)
if(i>>j&1) tmp += a[l][j];
else tmp-=a[l][j];
sum[k][i] = tmp;
//printf("sta = %d : %lld\n",i,sum[k][i]);
}
return ;
}
int mid = (l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
push(k,l,r);
}
void Modify(int k,int l,int r,int pos){
if(l == r){
for(int i=0;i<MAX;i++){
ll tmp = 0;
for(int j=0;j<m;j++)
if(i>>j&1) tmp += a[l][j];
else tmp-=a[l][j];
sum[k][i] = tmp;
}
return ;
}
int mid = (l+r)/2;
if(pos <= mid) Modify(k<<1,l,mid,pos);
else Modify(k<<1|1,mid+1,r,pos);
push(k,l,r);
}
ll ans = 0;
ll pre[50];
void query(int k,int l,int r,int x,int y){
if(x<=l && y>=r){
ans = max(ans,mx[k]);
for(int i=0;i<MAX;i++) ans = max(ans,max(pre[i]+sum[k][(MAX-1)^i],pre[(MAX-1)^i]+sum[k][i]));
for(int i=0;i<MAX;i++) pre[i] = max(pre[i],sum[k][i]);
return ;
}
int mid = (l+r)/2;
if(x<=mid) query(k<<1,l,mid,x,y);
if(y>mid) query(k<<1|1,mid+1,r,x,y);
}
int main(){
read(n);read(m);
MAX = 1<<m;
for(int i=1;i<=n;i++){
for(int k=0;k<m;k++)
read(a[i][k]);
}
build(1,1,n);
//debug(mx[1]);
read(p);
for(int i=1;i<=p;i++){
int op,x,y;
read(op);
if(op == 1){
read(x);
for(int k=0;k<m;k++)read(a[x][k]);
Modify(1,1,n,x);
}else{
read(x);read(y);
ans = -INF;
for(int k=0;k<MAX;k++) pre[k] = -INF;
query(1,1,n,x,y);
dl(ans);
}
}
return 0;
}
/**
2 2
-1 -2
4 5
**/