题目链接: http://codeforces.com/contest/1093/problem/G
在一个K维空间中给出N个点,M个询问,每次询问一段区间的点中相距最远的距离
数据范围: N , M < 2 ∗ 1 0 5 . K < = 5 N ,M< 2*10^5 .K < =5 N,M<2∗105.K<=5
我们先举出两个点时的情况
|a1-b1| + |a2-b2|
a1-b1+a2-b2
a1-b1-a2+b2
-a1+b1+a2-b2
-a1+b1-a2+b2
每一维的组合方案 2
总的组合方案 2^k
再次转换
a1+a2 -b1-b2
a1-a2 -b1+b2
-a1+a2 +b1-b2
-a1-a2 +b2+b2
如果我们将其拆成每块单独表示时,会发现前面的符号与后面的符号都是相反的
所以我们在拆成2^k时注意每一种情况的最大值与其相反符号的最大值相加
那么会不会出现,自己和自己相加的情况呢
不可能,这样的结果一定是0
因为前后符号相反,相互抵消,变成了0
所以,我们只需要开一个 2 K 2^K 2K 个线段树,每次维护最大值就好了
#include
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define debug(x) cerr<<#x<<":"<
#define pb push_back
typedef long long ll;
const int MAXN = 1e6+7;
#define lson rt<<1
#define rson rt<<1|1
int sum[MAXN][33];
int A[MAXN][33];
int B[MAXN][6];
void Build(int l,int r,int rt,int id) {
if (l == r) {
sum[rt][id] = A[l][id];
return ;
}
int m = l+r>>1;
Build(l,m,lson,id);
Build(m+1,r,rson,id);
sum[rt][id] = max(sum[lson][id] , sum[rson][id]);
}
void Update(int L,int val,int id,int l,int r,int rt) {
if (l == r) {
sum[rt][id] = val;
return ;
}
int m = l+r>>1;
if (L <= m) Update(L,val,id,l,m,lson);
else Update(L,val,id,m+1,r,rson);
sum[rt][id] = max(sum[lson][id], sum[rson][id]);
}
int Query(int L,int R,int id,int l,int r,int rt) {
if (L <= l && r <= R) {
return sum[rt][id];
}
int mx = -1e9,m = l+r>>1;
if (L <= m) mx = max(Query(L,R,id,l,m,lson),mx);
if (R > m) mx = max(Query(L,R,id,m+1,r,rson),mx);
return mx;
}
int N,K,M;
int ans[33];
void debugt(int l,int r,int rt,int id) {
if (l == r) {
cout << l << ":" << sum[rt][id] << ' ';
return;
}
int m = l+r>>1;
debugt(l,m,lson,id);
debugt(m+1,r,rson,id);
}
int main()
{
scanf("%d %d",&N,&K);
rep(i,1,N) {
rep(j,1,K) scanf("%d",&B[i][j]);
rep(j,0,(1<<K)-1) {
rep(k,0,K-1) {
if (j>>k&1) A[i][j] += B[i][k+1];
else A[i][j] -= B[i][k+1];
}
}
}
rep(j,0,(1<<K)-1) Build(1,N,1,j);
scanf("%d",&M);
rep(ii,1,M) {
int op,l,r,L;
scanf("%d",&op);
if (op == 1) {
scanf("%d",&L);
rep(j,1,K) scanf("%d",&B[L][j]);
rep(j,0,(1<<K)-1) {
A[L][j] = 0;
rep(k,0,K-1) {
if (j>>k&1) A[L][j] += B[L][k+1];
else A[L][j] -= B[L][k+1];
}
Update(L,A[L][j],j,1,N,1);
}
}else {
scanf("%d %d",&l,&r);
rep(j,0,(1<<K)-1) {
ans[j] = Query(l,r,j,1,N,1);
}
int res = -1e9;
rep(j,0,(1<<K)-1) {
int tj = (1<<K)-1-j;
res = max(res,ans[j]+ans[tj]);
}
printf("%d\n",res);
}
}
}