题目链接
https://codeforces.com/contest/1093/problem/G
http://acm.hdu.edu.cn/showproblem.php?pid=6435
解题思路
将K维曼哈顿距离表达式展开:
∑
i
=
1
k
∣
a
x
,
i
−
a
y
,
i
∣
=
∑
i
=
1
k
c
i
(
a
x
,
i
−
a
y
,
i
)
=
∑
i
=
1
k
c
i
a
x
,
i
−
∑
i
=
1
k
c
i
a
y
,
i
\sum_{i = 1}^{k}\left|a_{x,i} - a_{y,i}\right|=\sum_{i = 1}^{k}c_i(a_{x,i}-a_{y,i})=\sum_{i = 1}^{k}c_ia_{x,i}-\sum_{i = 1}^{k}c_ia_{y,i}
∑i=1k∣ax,i−ay,i∣=∑i=1kci(ax,i−ay,i)=∑i=1kciax,i−∑i=1kciay,i
当
a
x
,
i
≥
a
y
,
i
a_{x,i} \ge a_{y,i}
ax,i≥ay,i时,
c
i
=
1
c_i = 1
ci=1,否则
c
i
=
−
1
c_i = -1
ci=−1。
每个点的
c
i
c_i
ci共有
2
k
2^k
2k种状态,可用二进制表示,该位为1,则
c
i
=
1
c_i = 1
ci=1,否则
c
i
=
−
1
c_i = -1
ci=−1。
求任意两点的K维最远曼哈顿距离,即可枚举
2
k
2^k
2k种状态,用该状态下最大的
∑
i
=
1
k
c
i
a
x
,
i
\sum_{i = 1}^{k}c_ia_{x,i}
∑i=1kciax,i减最小的
∑
i
=
1
k
c
i
a
y
,
i
\sum_{i = 1}^{k}c_ia_{y,i}
∑i=1kciay,i来更新答案。
然而这样会出现与事实不符的情况,如当前状态的二进制表示为xxx1x,但最大的
∑
i
=
1
k
c
i
a
x
,
i
\sum_{i = 1}^{k}c_ia_{x,i}
∑i=1kciax,i中,
a
x
,
4
=
3
a_{x,4} = 3
ax,4=3,最小的
∑
i
=
1
k
c
i
a
y
,
i
\sum_{i = 1}^{k}c_ia_{y,i}
∑i=1kciay,i中,
a
y
,
4
=
5
a_{y,4} = 5
ay,4=5,显然
c
4
=
−
1
c_4=-1
c4=−1,第四位应该为0。但这种情况下,
c
4
a
x
,
4
−
c
4
a
y
,
4
=
−
2
c_4a_{x,4}-c_4a_{y,4}=-2
c4ax,4−c4ay,4=−2,一定存在xxx0x的状态,
c
4
a
x
,
4
−
c
4
a
y
,
4
=
2
c_4a_{x,4}-c_4a_{y,4}=2
c4ax,4−c4ay,4=2,与事实相符且累加后优于xxx1x。
CodeForces 1093G:
1、单点更新
2、区间求K维最远曼哈顿距离
线段树维护每个点的
2
k
2^k
2k种状态,时间复杂度
(
n
+
q
)
2
k
log
n
(n + q)2^k\log n
(n+q)2klogn。
HDU 6435:
(
S
x
+
∑
i
=
1
k
c
i
a
x
,
i
)
+
(
S
y
+
∑
i
=
1
k
(
−
c
i
)
a
y
,
i
)
(S_x + \sum_{i = 1}^{k}c_ia_{x,i})+(S_y +\sum_{i = 1}^{k}(-c_i)a_{y,i})
(Sx+∑i=1kciax,i)+(Sy+∑i=1k(−ci)ay,i)
枚举
2
k
2^k
2k种状态,用该状态下最大的
S
x
+
∑
i
=
1
k
c
i
a
x
,
i
S_x + \sum_{i = 1}^{k}c_ia_{x,i}
Sx+∑i=1kciax,i,加按位取反后,最大的
S
y
+
∑
i
=
1
k
c
i
a
y
,
i
S_y +\sum_{i = 1}^{k}c_ia_{y,i}
Sy+∑i=1kciay,i来更新答案。
AC代码
//CodeForces 1093G
#include<bits/stdc++.h>
#define SZ(x) (int)(x.size())
using namespace std;
const int MAXN = 200010;
int n, k, q, b[5];
struct STree{
int ma[32];
#define lson p << 1
#define rson p << 1 | 1
#define ma(x, y) st[x].ma[y]
}st[MAXN << 2];
void upd(int p, int l, int r, int x, int b[]){
if(l == r){
for(int i = 0; i < (1 << k); i ++){
ma(p, i) = 0;
for(int j = 0; j < k; j ++){
if((i >> j) & 1)
ma(p, i) += b[j];
else
ma(p, i) -= b[j];
}
}
return ;
}
int mid = l + r >> 1;
if(x <= mid)
upd(lson, l, mid, x, b);
else
upd(rson, mid + 1, r, x, b);
for(int i = 0; i < (1 << k); i ++)
ma(p, i) = max(ma(lson, i), ma(rson, i));
}
int ask(int p, int l, int r, int ql, int qr, int c){
if(ql <= l && r <= qr)
return ma(p, c);
int mid = l + r >> 1, ans = -1e7;
if(ql <= mid)
ans = max(ans, ask(lson, l, mid, ql, qr, c));
if(qr > mid)
ans = max(ans, ask(rson, mid + 1, r, ql, qr, c));
return ans;
}
int main(){
cin >> n >> k;
for(int i = 1; i <= n; i ++){
for(int j = 0; j < k; j ++)
scanf("%d", b + j);
upd(1, 1, n, i, b);
}
cin >> q;
while(q --){
int op, l, r; scanf("%d", &op);
if(op == 1){
scanf("%d", &l);
for(int i = 0; i < k; i ++)
scanf("%d", b + i);
upd(1, 1, n, l, b);
}
else{
scanf("%d%d", &l, &r);
int ans = 0;
for(int i = 0; i < (1 << k); i ++)
ans = max(ans, ask(1, 1, n, l, r, i) + ask(1, 1, n, l, r, ((1 << k) - 1) ^ i));
printf("%d\n", ans);
}
}
return 0;
}
//HDU 6435
#include<bits/stdc++.h>
#define SZ(x) (int)(x.size())
using namespace std;
typedef long long ll;
const int MAXN = 100010;
int n, m, k, a[MAXN][6];
ll ma[32];
int main(){
int T; cin >> T;
while(T --){
cin >> n >> m >> k;
for(int i = 0; i < (1 << k); i ++)
ma[i] = -1e12;
for(int i = 1; i <= n; i ++)
for(int j = 0; j <= k; j ++)
scanf("%d", &a[i][j]);
for(int i = 1; i <= n; i ++){
for(int t = 0; t < (1 << k); t ++){
ll cur = a[i][0];
for(int j = 0; j < k; j ++){
if((t >> j) & 1)
cur += a[i][j + 1];
else
cur -= a[i][j + 1];
}
ma[t] = max(ma[t], cur);
}
}
ll ans = -1e12;
for(int i = 1; i <= m; i ++){
for(int j = 0; j <= k; j ++)
scanf("%d", &a[i][j]);
for(int t = 0; t < (1 << k); t ++){
ll cur = a[i][0];
for(int j = 0; j < k; j ++){
if((t >> j) & 1)
cur += a[i][j + 1];
else
cur -= a[i][j + 1];
}
ans = max(ans, cur + ma[((1 << k) - 1) ^ t]);
}
}
cout << ans << '\n';
}
return 0;
}