题目传送门

以二维为例,二维下两点间的曼哈顿距离最大值为\(max(|x_i-x_j| + |y_i-y_j|)\),可以通过枚举坐标符号正负来去掉绝对值。即\(max(x_i-x_j+y_i-y_j,x_i+x_j+y_i-y_j...)\)共16种情况。设\(f[i][t]\)表示第\(i\)个点各维度数值正负状态为\(t\)时的值,假如二维向量\(p[i]=(1,2)\),那么状态\(t\)的范围为\([0,3]\),如果\(t=2\),即二进制表示为\(10\),那么\(p\)向量第一维数值加个负号,第二维数值不变,类似状压过程。对于每个向量处理出\(f\)的值。最终结果即在\([l,r]\)范围内求\(max(f[i][m],f[j][n])(m+n=(1<<k)-1)\),具体用线段树实现。

#include<cstdio>
#include<vector>
#include<algorithm>
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int N = 2e5 + 50; struct Node{
vector<int> val;
Node() { val.resize(35); }
}node[N << 2]; int n, k, q;
int a[N][6]; void Max(const vector<int> &x, const vector<int> &y, vector<int> &z){
for(int i = 0; i < (1 << k); ++i) z[i] = max(x[i], y[i]);
} void Max(const vector<int> &x, vector<int> &y){
for(int i = 0; i < (1 << k); ++i) y[i] = max(x[i], y[i]);
} void build(int u, int l, int r){
if(l == r){
for(int s = 0; s < (1 << k); ++s){
for(int t = 1; t <= k; ++t){
if(s & (1 << (t - 1))) node[u].val[s] += a[l][t];
else node[u].val[s] -= a[l][t];
}
}
return ;
}
int mid = (l + r) >> 1;
if(l <= mid) build(ls, l, mid);
if(r > mid) build(rs, mid + 1, r);
Max(node[ls].val, node[rs].val, node[u].val);
} void modify(int u, int l, int r, int pos){
if(l == r){
for(int i = 0; i < (1 << k); ++i) node[u].val[i] = 0;
for(int s = 0; s < (1 << k); ++s){
for(int t = 1; t <= k; ++t){
if(s & (1 << (t - 1))) node[u].val[s] += a[l][t];
else node[u].val[s] -= a[l][t];
}
}
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid) modify(ls, l, mid, pos);
else modify(rs, mid + 1, r, pos);
Max(node[ls].val, node[rs].val, node[u].val);
} vector<int> ans(35); void query(int u, int l, int r, int ql, int qr){
if(ql <= l && qr >= r){
Max(node[u].val, ans);
return ;
}
int mid = (l + r) >> 1;
if(ql <= mid) query(ls, l, mid, ql, qr);
if(qr > mid) query(rs, mid + 1, r, ql, qr);
} int main(){
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i)
for(int t = 1; t <= k; ++t)
scanf("%d", &a[i][t]);
build(1, 1, n);
scanf("%d", &q);
while(q--){
int opt, id, l, r;
scanf("%d", &opt);
if(opt == 1){
scanf("%d", &id);
for(int i = 1; i <= k; ++i) scanf("%d", &a[id][i]);
modify(1, 1, n, id);
}
else{
for(int i = 0; i < 35; ++i) ans[i] = -1e9;
scanf("%d%d", &l, &r);
query(1, 1, n, l, r);
int maxx = 0;
for(int s = 0; s < (1 << k); ++s){
maxx = max(maxx, ans[s] + ans[(1 << k) - 1 - s]);
}
printf("%d\n", maxx);
}
}
}

Educational Codeforces Round 56 (Rated for Div. 2) G题(线段树,曼哈顿距离)的更多相关文章

  1. Educational Codeforces Round 81 (Rated for Div. 2)E(线段树)

    预处理把左集划分为大小为1~i-1时,把全部元素都移动到右集的代价,记作sum[i]. 然后枚举终态时左集的大小,更新把元素i 留在/移动到 左集的代价. 树状数组/线段树处理区间修改/区间查询 #d ...

  2. Educational Codeforces Round 73 (Rated for Div. 2)F(线段树,扫描线)

    这道题里线段树用来区间更新(每次给更大的区间加上当前区间的权重),用log的复杂度加快了更新速度,也用了区间查询(查询当前区间向右直至最右中以当前区间端点向右一段区间的和中最大的那一段的和),也用lo ...

  3. Educational Codeforces Round 72 (Rated for Div. 2)E(线段树,思维)

    #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;#define BUF_SIZE 100000 ...

  4. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

  5. Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))

    题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...

  6. Educational Codeforces Round 56 (Rated for Div. 2) D. Beautiful Graph 【规律 && DFS】

    传送门:http://codeforces.com/contest/1093/problem/D D. Beautiful Graph time limit per test 2 seconds me ...

  7. Educational Codeforces Round 56 (Rated for Div. 2) ABCD

    题目链接:https://codeforces.com/contest/1093 A. Dice Rolling 题意: 有一个号数为2-7的骰子,现在有一个人他想扔到几就能扔到几,现在问需要扔多少次 ...

  8. Educational Codeforces Round 56 (Rated for Div. 2) D

    给你一个无向图 以及点的个数和边  每个节点只能用1 2 3 三个数字 求相邻 两个节点和为奇数   能否构成以及有多少种构成方法 #include<bits/stdc++.h> usin ...

  9. Educational Codeforces Round 56 (Rated for Div. 2)

    涨rating啦.. 不过话说为什么有这么多数据结构题啊,难道是中国人出的? A - Dice Rolling 傻逼题,可以用一个三加一堆二或者用一堆二,那就直接.. #include<cstd ...

  10. Educational Codeforces Round 56 (Rated for Div. 2) F - Vasya and Array dp好题

    F - Vasya and Array dp[ i ][ j ] 表示用了前 i 个数字并且最后一个数字是 j 的方案数. dp[ i ][ j ] = sumdp [i - 1 ][ j ], 这样 ...

随机推荐

  1. nodejs端模块化方式comomjs详解

    nodejs端实现模块化的方式通常是通过commonjs,使用模块化可以复用js代码,使得逻辑结构更为清晰. commonjs的语法规则如下通过 module.exports 或者 exports 导 ...

  2. [pandas]从多个文件中构建dataframe

    按列从多个文件中构建 假设有两个csv文件,列不相同,需要整合为一个dataframe,使用glob模块: from glob import glob import pandas as pd # gl ...

  3. 清理MySQL的binlog历史文件

    前言 系统版本:centos 7 MySQL版本:5.7 mysql的binlog文件最好不要手动删,避免删错导致bin log同步异常. 步骤 查看当前的binlog文件 show binary l ...

  4. spring多数据源动态切换的实现原理及读写分离的应用

    简介 AbstractRoutingDataSource是Spring框架中的一个抽象类,可以实现多数据源的动态切换和路由,以满足复杂的业务需求和提高系统的性能.可扩展性.灵活性. 应用场景 多租户支 ...

  5. 《Pro Git》起步笔记

    @ 目录 什么是版本控制 本地版本控制系统 集中化的版本控制 分布式的版本控制系统 Git简史 Git是什么 安装Git 在Linux上安装 在Windows上安装 初次运行Git前的配置 用户信息 ...

  6. Hutool:一行代码搞定数据脱敏

    1. 什么是数据脱敏 1.1 数据脱敏的定义 数据脱敏百度百科中是这样定义的: 数据脱敏,指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护.这样就可以在开发.测试和其它非生产环境 ...

  7. Win10安装Oracle-21C

    1.前期工作 下载安装包:OracleXE213_Win64.zip 解压安装包 2.开始安装 注意:以管理员身份运行 ++++++++++++++++++++++分割线+++++++++++++++ ...

  8. 如何在linux上安装neovim0.9(以debian和ubuntu为例) – 东凭渭水流

    发布于 1 分钟前  3 次阅读 由于apt中只有neovim-0.72的安装包.想使用新版需要自己安装,以下是安装过程 1.首先需要卸载旧版neovim sudo remove neovim 2.从 ...

  9. AI绘画| 迪士尼风格|可爱头像【附Midjourney提示词】

    Midjourney案例分享 图片预览 迪士尼风格|可爱头像 高清原图及关键词Prompt已经放在文末网盘,需要的自取 在数字艺术的新时代,人工智能绘画已经迅速崭露头角.作为最先进的技术之一,AI绘画 ...

  10. 基于opencv-pyhton与opencv-c++的结合理解与学习

    2023年上半年,一直在学习opencv-c++版本,学习了其中的多个库函数 笔记链接:https://www.cnblogs.com/Tan-code/category/2339311.html o ...