IOI 2013 袋熊(线段树+分块+决策单调性)
题意
[http://www.ioi2013.org/wp-content/uploads/tasks/day1/wombats/Wombats zh (CHN).pdf](http://www.ioi2013.org/wp-content/uploads/tasks/day1/wombats/Wombats zh (CHN).pdf)
思路
我们设矩形的行数为 \(n(5000)\) ,列数为 \(m(200)\) ,更新次数为 \(U(500)\) ,查询次数为 \(Q(2\times 10^5)\) 。
最暴力的思想是一次更新处理出从一个 \(m^2\) 的数组,代表第一行的每一个点走到最后一行每一个点的最小代价,然后 \({\cal O}(1)\) 回答。处理出这样一个数组的代价是 \({\cal O}(nm^2)\) 的,于是我们得到了一个 \({\cal O}(Unm^2+Q)\) 的做法。
考虑到我们可以直接把上述二维数组看成矩阵,从而 \(\cal O(m^3)\) 的合并两个二维数组,那么在假如没有空间限制,我们就可以在 \(n\) 那一维上套线段树,从而做到 \({\cal O}(nm^3+Um^3\log n+Q)\) 的时间复杂度。
再仔细观察一下题设,我们发现在作矩阵乘法的时候。\(C(i,j)\leftarrow \displaystyle\min_k\{ A(i,k)+B(k,j)\}\) 随着 \(i\) 变大, 最后起更新作用的 \(k\) 变大;随着 \(j\) 变大, 最后起更新作用的 \(k\) 也变大。于是我们发现了决策单调性,一次矩阵乘法的复杂度降到了 \({\cal O}(m^2)\) 。这是本题最关键的结论,现在复杂度被降到了\({\cal O}(nm^2+Um^2\log n+Q)\) 。
这个算法在时间上已经没有问题了,但是空间开不下,于是我们想到了缩减 \(n\) 。不妨先对原序列进行分块,再以块为基本元素维护线段树即可。块内就直接用最开始讲的暴力做法 \({\cal O}(nm^2)\) 的更新(当然你也可以矩乘),线段树的 \(\text{push_up}\) 操作就是 \({\cal O}(m^2)\) 的矩乘。
设块大小是 \(S\) ,最终时间复杂度为 \(\displaystyle {\cal O}{\big(}nm^2+Um^2(S+\log{n\over S})+Q{\big )}\) ,空间复杂度为 \(\displaystyle {\cal O}(nm+{n\over S}m^2)\) 。块大小越小越好,只要不炸空间。
代码
#include<bits/stdc++.h>
#define FOR(i, x, y) for(register int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(register int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 5005;
const int M = 205;
const int S = 7;
int R[N][M], D[N][M];
int dp[(N / S + 5) << 2][M][M];
int ans[M][M]; bool mark;
int n, m, q;
inline int bid(int k) {return k / S;}
inline int bl(int k) {return std::max(1, k * S);}
inline int br(int k) {return std::min(n, (k + 1) * S - 1);}
void mul(int C[M][M], int A[M][M], int B[M][M])
{
static int s[M][M];
FOR(x, 0, m + 1) FOR(y, 0, m + 1) s[x][y] = -1;
FOR(x, 1, m)
DOR(y, m, 1)
{
C[x][y] = 2e9;
int l = 1, r = m;
if(~s[x - 1][y]) chk_max(l, s[x - 1][y]);
if(~s[x][y + 1]) chk_min(r, s[x][y + 1]);
FOR(z, l, r)
if(chk_min(C[x][y], A[x][z] + B[z][y]))
s[x][y] = z;
}
}
void construct(int x, int dp[M][M])
{
int u = bl(x), d = br(x);
FOR(i, 1, m)
{
dp[i][i] = 0;
int sum = 0;
DOR(j, i - 1, 1)
{
sum += R[u][j];
dp[i][j] = sum;
}
sum = 0;
FOR(j, i + 1, m)
{
sum += R[u][j - 1];
dp[i][j] = sum;
}
FOR(j, 1, m) dp[i][j] += D[u][j];
FOR(x, u + 1, d)
{
FOR(j, 2, m) chk_min(dp[i][j], dp[i][j - 1] + R[x][j - 1]);
DOR(j, m - 1, 1) chk_min(dp[i][j], dp[i][j + 1] + R[x][j]);
FOR(j, 1, m) dp[i][j] += D[x][j];
}
}
}
void build(int k, int l, int r)
{
if(l == r)
{
construct(l, dp[k]);
return;
}
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
mul(dp[k], dp[k << 1], dp[k << 1 | 1]);
}
void update(int k, int x, int l, int r)
{
if(l == r)
{
construct(l, dp[k]);
return;
}
int mid = (l + r) >> 1;
if(x <= mid) update(k << 1, x, l, mid);
else update(k << 1 | 1, x, mid + 1, r);
mul(dp[k], dp[k << 1], dp[k << 1 | 1]);
}
int main()
{
scanf("%d%d", &n, &m);
FOR(i, 1, n) FOR(j, 1, m - 1) scanf("%d", &R[i][j]);
FOR(i, 1, n - 1) FOR(j, 1, m) scanf("%d", &D[i][j]);
build(1, bid(1), bid(n));
scanf("%d", &q);
while(q--)
{
int cmd, u, v, w;
scanf("%d%d%d", &cmd, &u, &v);
u++, v++;
if(cmd == 1)
{
scanf("%d", &w);
R[u][v] = w;
update(1, bid(u), bid(1), bid(n));
}
else if(cmd == 2)
{
scanf("%d", &w);
D[u][v] = w;
update(1, bid(u), bid(1), bid(n));
}
else if(cmd == 3)
printf("%d\n", dp[1][u][v]);
}
return 0;
}
IOI 2013 袋熊(线段树+分块+决策单调性)的更多相关文章
- [Noi2016]区间[离散化+线段树维护+决策单调性]
4653: [Noi2016]区间 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 621 Solved: 329[Submit][Status][D ...
- 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)
题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...
- BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...
- [luogu1198][bzoj1012][JSOI2008]最大数【线段树+分块】
题目描述 区间查询最大值,结尾插入,强制在线. 分析 线段树可以做,但是练了一下分块,发现自己打错了两个地方,一个是分块的地方把/打成了%,还有是分块的时候标号要-1. 其他也没什么要多讲的. 代码 ...
- L3-2 森森快递 (30 分)(贪心+线段树/分块)
题目链接:https://pintia.cn/problem-sets/1108203702759940096/problems/1108204121661857798 题目大意: 森森开了一家快递公 ...
- 计蒜客16492 building(二分线段树/分块)
题解: 考虑用线段树维护楼的最大值,然后这个问题就很简单了. 每次可以向左二分出比x高的第一个楼a,同理也可以向右二分出另一个楼b,如果a,b都存在,答案就是b-a-1. 注意到二分是可以直接在线段树 ...
- CF-558E (线段树/分块)
解题思路: 很显然突破口就是字符集比较小,分块和线段树都能A 话说线段树时间是分块5倍啊 代码(线段树): #include<cstdio> #include<cstring> ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- 【模拟8.05】优美序列(线段树 分块 ST算法)
如此显然的线段树,我又瞎了眼了 事实上跟以前的奇袭很像....... 只要满足公式maxn-minn(权值)==r-l即可 所以可以考虑建两颗树,一棵节点维护位置,一棵权值, 每次从一棵树树上查询信息 ...
随机推荐
- Vue.js 源码分析(二十六) 高级应用 作用域插槽 详解
普通的插槽里面的数据是在父组件里定义的,而作用域插槽里的数据是在子组件定义的. 有时候作用域插槽很有用,比如使用Element-ui表格自定义模板时就用到了作用域插槽,Element-ui定义了每个单 ...
- 「ASCII 流程图」工具——Graph Easy
https://juejin.im/post/5a09c43451882535c56c6bbf 「ASCII 流程图」工具——Graph Easy // 1. brew install graphvi ...
- linux安装redis步骤
1.安装gcc redis是c语言编写的 -- 安装命令 yum install gcc-c++ -- 检查gcc 是否安装 gcc -v 2.下载redis安装包,在root目录下执行 wget ...
- Node.js能解决什么问题?
一.使用Node.js能解决什么问题 对于PHP.JAVA.Python等服务端语言中,为每个客户端连接创建一个新的线程,而每个线程需要大约2M的内存,理论上,具有8GB内存的服务器可以同时连接的最大 ...
- WPF 动态资源 DataContext="{DynamicResource studentListKey}" DisplayMemberPath="Name"
public class StudentList:ObservableCollection<Student> { public List<Student> studentLis ...
- CSS3制作文字背景图
文字带上渐变色,或者说让文字透出图片.这些效果 CSS 属性也可以完成. 方法一.利用CSS3属性mix-blend-mode:lighten;实现 使用 mix-blend-mode 能够轻易实现, ...
- elasticsearch 入门篇
前言: 要论入门最好的文档,非elasticsearch权威指南和官方的开发文档莫属,我只是基于这两份文档,记录一些关键知识点和自己的理解. 我们为什么要用elasticsearch,或者说来解决什么 ...
- QQ和微信点击链接或扫描自动跳转外部浏览器
微信上进行的网页宣传.游戏传播.APP下载各类活动很多,但是各位朋友肯定经常会遇到一些特殊需求,网页需要在手机默认浏览器打开而不是微信内置浏览器.这个问题怎么解决呢? 另一种情况是你的网址被恶意举报被 ...
- SpringData系列四 @Query注解及@Modifying注解@Query注解及@Modifying注解
@Query注解查询适用于所查询的数据无法通过关键字查询得到结果的查询.这种查询可以摆脱像关键字查询那样的约束,将查询直接在相应的接口方法中声明,结构更为清晰,这是Spring Data的特有实现. ...
- xshell5运行hadoop集群
---恢复内容开始--- 1.CentOS主机配置 在配置Hadoop过程中,防火墙必须优先关闭SELinux,否则将影响后续Hadoop配置与使用,命令如下: # 查看 “系统防火墙” 状态命令 s ...