【Codeforces 1093G】Multidimensional Queries | 线段树、曼哈顿距离

题目大意:

给出一个 n n n k k k元组 ( k ≤ 5 ) (k \le 5) (k5),支持两种操作:

  • 1   i   ( b 1 , b 2 , b 3 , ⋯ b k ) 1\ i \ (b_1,b_2,b_3,\cdots b_k) 1 i (b1,b2,b3,bk),将第 i i i k k k元组置换为当前 k k k元组
  • 2   l   r 2 \ l \ r 2 l r ,询问 [ l , r ] [l,r] [l,r]区间内两两之间最大的曼哈顿距离

题目思路:

转换为 k k k维空间问题。

两两之间的曼哈顿距离最大值就是将带绝对值的曼哈顿距离符号拆开所有情况中的最大值。

所以将此看成一个 k k k维曼哈顿距离,就可以将其状压了。

状压之后维护一个线段树即可。

Code:

/*** 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
**/

你可能感兴趣的:(【Codeforces 1093G】Multidimensional Queries | 线段树、曼哈顿距离)