题面传送门

首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times 200\) 的数组 \(d_{i,j}\) 表示从 \((l,i)\) 到 \((r,j)\) 的最短路,合并暴力用类似 floyd 的方式进行转移,这样暴力时间复杂度是 \(RC^3+mC^2\log R+q\),空间复杂度 \(RC^2\),其中 \(m\) 为修改次数,一脸无法通过,而且 TL ML 双开花(大雾。

考虑优化这个暴力,由于线段树建树就有个 \(R\),因此这个 \(R\) 是去不掉的,要优化也只能把这个 \(c^3\) 优化掉。注意到一件事情,就是当我们固定上端点(\(i\))时,随着 \(j\) 的增大,\(d_{i,j}\) 的决策点是单调不降的,因为如果出现某个 \(d_{i,j}\) 的决策点 \(p\) 小于 \(d_{i,j+1}\) 的决策点 \(q\),否则 \(i\to j\) 与 \(i\to j+1\) 的最短路径一定有个交点 \(P\),且这个 \(P\) 一定在 \([l,r]\) 中后方(\(>\dfrac{l+r}{2}\)),因此 \(i\to j\) 和 \(i\to j+1\) 这两个最优路径在 \(i\to P\) 的部分不重合,如果这两段长度相等那么我们可以把它们交换一下,答案不变却满足决策点单调性,否则我们完全可以把长度小的一段并到长度大的一段上去,答案更优。对于固定下断点的情况也同理,因此假设 \(p_{i,j}\) 为 \(d_{i,j}\) 的决策点,那么有 \(p_{i-1,j}\le p_{i,j}\le p_{i,j+1}\),决策单调性优化一下可以搞到 \(c^2\)。

这样 TL 倒是 ok 了,可 ML 还是会炸,这里又有一个 trick,我们设一个阈值 \(B\) 当区间长度很小,不超过 \(B\) 时候,直接暴力枚举起点 \(dp\) 求出最短路径即可,这样暴力 DP 复杂度是 \(BC^2\) 的,而我们建树时会 DP \(\dfrac{R}{B}\) 次,每次修改都会 DP 一次,因此空间复杂度是 \(\dfrac{R}{B}C^2\),时间复杂度 \(RC^3+mC^2\log R+q+mBC^2\),刚好卡过去。

据说这东西有个名字叫线段树分块?长见识了(

const int MAXN=5e3;
const int MAXC=200;
const int MAXP=MAXN*4/20;
const int INF=0x3f3f3f3f;
int n,m,hor[MAXN+5][MAXC+5],ver[MAXN+5][MAXC+5];
struct value{
int a[MAXC+5][MAXC+5];
value(){memset(a,63,sizeof(a));}
};
int p[MAXC+5][MAXC+5];
value merge(value a,value b,int vx){
value c;memset(p,0,sizeof(p));
for(int i=1;i<=m;i++) for(int j=m;j;j--){
for(int k=((p[i-1][j])?(p[i-1][j]):1);k<=((p[i][j+1])?p[i][j+1]:m);k++)
if(c.a[i][j]>a.a[i][k]+b.a[k][j]+ver[vx][k])
c.a[i][j]=a.a[i][k]+b.a[k][j]+ver[vx][k],p[i][j]=k;
} return c;
}
struct node{int l,r;value v;} s[MAXP+5];
int dp[MAXN+5][MAXC+5];
value get(int u,int d){
value res;
for(int i=1;i<=m;i++){
for(int j=u;j<=d;j++) for(int k=1;k<=m;k++) dp[j][k]=INF;
dp[u][i]=0;
for(int j=u;j<=d;j++){
if(j!=u) for(int k=1;k<=m;k++) dp[j][k]=dp[j-1][k]+ver[j-1][k];
for(int k=2;k<=m;k++) chkmin(dp[j][k],dp[j][k-1]+hor[j][k-1]);
for(int k=m-1;k;k--) chkmin(dp[j][k],dp[j][k+1]+hor[j][k]);
}
// for(int j=u;j<=d;j++) for(int k=1;k<=m;k++) printf("%d%c",dp[j][k]," \n"[k==m]);
for(int j=1;j<=m;j++) res.a[i][j]=dp[d][j];
} return res;
}
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(r-l<=20) return s[k].v=get(l,r),void();
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
s[k].v=merge(s[k<<1].v,s[k<<1|1].v,mid);
}
void modify(int k,int x){
if(s[k].r-s[k].l<=20) return s[k].v=get(s[k].l,s[k].r),void();int mid=s[k].l+s[k].r>>1;
(x<=mid)?modify(k<<1,x):modify(k<<1|1,x);s[k].v=merge(s[k<<1].v,s[k<<1|1].v,mid);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) for(int j=1;j<m;j++) scanf("%d",&hor[i][j]);
for(int i=1;i<n;i++) for(int j=1;j<=m;j++) scanf("%d",&ver[i][j]);
build(1,1,n);int qu;scanf("%d",&qu);
while(qu--){
int opt;scanf("%d",&opt);
if(opt==1){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
++x;++y;hor[x][y]=z;modify(1,x);
} else if(opt==2){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
++x;++y;ver[x][y]=z;modify(1,x);
} else {
int x,y;scanf("%d%d",&x,&y);++x;++y;
printf("%d\n",s[1].v.a[x][y]);
}
}
return 0;
}

洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)的更多相关文章

  1. luogu P5892 [IOI2014]holiday 假期 决策单调性优化dp 主席树

    LINK:holiday 考虑第一个subtask. 容易想到n^2暴力枚举之后再暴力计算答案. 第二个subtask 暴力枚举终点可以利用主席树快速统计答案. 第三个subtask 暴力枚举两端利用 ...

  2. 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)

    点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...

  3. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  4. CF868F Yet Another Minimization Problem 分治决策单调性优化DP

    题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...

  5. 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)

    传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...

  6. [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)

    第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...

  7. BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】

    Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt( ...

  8. 决策单调性优化dp 专题练习

    决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...

  9. 算法学习——决策单调性优化DP

    update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...

随机推荐

  1. JVM详解(六)——对象的实例化、内存布局与访问定位

    一.对象的实例化 1.创建对象的方式 2.创建对象的步骤 脑图:https://www.processon.com/view/link/61701a927d9c087040525226 3.对象属性赋 ...

  2. 经典论文系列 | 缩小Anchor-based和Anchor-free检测之间差距的方法:自适应训练样本选择

    ​  前言  本文介绍一篇CVPR2020的论文,它在paperswithcode上获得了16887星,谷歌学术上有261的引用次数. 论文主要介绍了目标检测现有的研究进展.anchor-based和 ...

  3. Apache Zookeeper Java客户端Curator使用及权限模式详解

    这篇文章是让大家了解Zookeeper基于Java客户端Curator的基本操作,以及如何使用Zookeeper解决实际问题. Zookeeper基于Java访问 针对zookeeper,比较常用的J ...

  4. 什么是关系图 (ERD)?

    首先,什么是实体关系图? 实体关系图,也称为ERD,ER图或ER模型,是一种用于数据库设计的结构图.一个ERD包含不同的符号和连接器,它们可视化两个重要信息:系统范围内的主要实体,以及这些实体之间的相 ...

  5. 2021.9.26考试总结[NOIP模拟62]

    T1 set 从\(0\)到\(n\)前缀余数有\(n+1\)个,但只有\(n\)种取值,找到一样的两个输出区间即可. \(code:\) T1 #include<bits/stdc++.h&g ...

  6. 不可错过的stm32单片机直流电机驱动与测速详解

    stm32直流电机驱动与测速 说实话就现在的市场应用中stm32已经占到了绝对住到的地位,51已经成为过去式,32的功能更加强大,虽然相应的难度有所增加,但是依然阻止不了大家学习32的脚步,不说大话了 ...

  7. ICPC Mid-Central USA Region 2019 题解

    队友牛逼!带我超神!蒟蒻的我还是一点一点的整理题吧... Dragon Ball I 这个题算是比较裸的题目吧....学过图论的大概都知道应该怎么做.题目要求找到七个龙珠的最小距离.很明显就是7个龙珠 ...

  8. hdu 2200 Eddy's AC难题(简单数学。。)

    题意: N个人,每个人AC的题数都不一样. Eddy想从中选出一部分人(或者全部)分成两组.必须满足第一组中的最小AC数大于第二组中的最大AC数. 问共有多少种不同的选择方案. 思路: 简单数学.. ...

  9. spark structured-streaming 最全的使用总结

    一.spark structured-streaming  介绍 我们都知道spark streaming  在v2.4.5 之后 就进入了维护阶段,不再有新的大版本出现,而且 spark strea ...

  10. 寒武纪加速平台(MLU200系列) 摸鱼指南(一)--- 基本概念及相关介绍

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...