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来更新答案。
//CodeForces 1093G
#include
#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
#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;
}