LuoguP5897 [IOI2013]wombats

题目描述

简要题意:有一个R∗CR*CR∗C的网格图,边有边权,支持修改,多次询问V1,V2V_1,V_2V1​,V2​,求点(0,V1)(0,V_1)(0,V1​)到(R−1,V2)(R-1,V_2)(R−1,V2​)的最短路(只能往左右和往下走)。

Solution

记f[i][j]f[i][j]f[i][j]表示从(0,i)(0,i)(0,i)到(0,j)(0,j)(0,j)的最短路,可以通过一行一行DPDPDP在O(R∗C2)O(R*C^2)O(R∗C2)的时间内求得,而每次修改需要重新求答案,所以时间复杂度为O(R∗C2∗Q)O(R*C^2*Q)O(R∗C2∗Q)。

但我们发现这题的RRR很大,而CCC很小,所以我们考虑把RRR这一位扔到线段树上,线段树的一个区间记录了一个C∗CC*CC∗C的矩阵。线段[l,r][l,r][l,r]中矩阵的一个点Di,jD_{i,j}Di,j​记录从(l,i)(l,i)(l,i)到(r,j)(r,j)(r,j)的距离,这样每次修改就只需要修改lognlog^nlogn。

接下来考虑两个线段怎么合并,如果暴力枚举的话时间复杂度为O(n3)O(n^3)O(n3)(类似floydfloydfloyd的方法,枚举i,ji,ji,j和中间点kkk),但我们发现这里有决策单调性,我们固定一个点iii,枚举jjj,假设jjj的最优决策点为kkk,那么对于任意的j′>jj'>jj′>j,j′j'j′的最优决策点k′>kk'>kk′>k,这样就可以通过分治做到O(n2lgn)O(n^2lgn)O(n2lgn)或直接记录决策点位置做到O(n2)O(n^2)O(n2)。

这样优化之后时间复杂度就OKOKOK了。然而空间还是太大了,于是有一个神奇的套路:在线段树中,若线段的长度小于一个阈值ttt,则通过之前说的O(n3)O(n^3)O(n3)暴力求解DDD矩阵。

我的程序当阈值设为20的时候能过。
所以时空复杂度就是O(能过)O(能过)O(能过)了(懒得算QAQ)

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=998244353;
const int MAXN=5005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
int n,m,d1[MAXN][205],d2[MAXN][205],s[MAXN][205],tmp[205][205];
struct Matrix
{int A[205][205],l,r;void clear(int L,int R) {l=L,r=R;for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) A[i][j]=INF;}Matrix(int L=0,int R=0) { clear(L,R); }void rebuild(int L,int R){l=L,r=R;for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) A[i][j]=abs(s[l][i]-s[l][j]);for (int k=l+1;k<=r;k++){for (int i=1;i<=m;i++)for (int j=1;j<=m;j++) A[i][j]+=d2[k][j],tmp[i][j]=A[i][j];for (int i=1,smin;i<=m;i++){smin=tmp[i][1];for (int j=2;j<=m;j++) smin+=d1[k][j],upmin(smin,tmp[i][j]),upmin(A[i][j],smin);smin=tmp[i][m];for (int j=m-1;j>=1;j--) smin+=d1[k][j+1],upmin(smin,tmp[i][j]),upmin(A[i][j],smin);}}}void print(){cout<<l<<" "<<r<<endl;for (int i=1;i<=m;i++){for (int j=1;j<=m;j++) cout<<A[i][j]<<" ";cout<<endl;}cout<<endl;}
} ans;
struct Segment_Tree
{Matrix tree[1005];void Solve(Matrix &x,Matrix &y,int t,int l,int r,int L,int R){   int mid=(l+r)>>1,k=L;for (int i=L+1;i<=R;i++)if (x.A[t][i]+d2[y.l][i]+y.A[i][mid]<x.A[t][k]+d2[y.l][k]+y.A[k][mid]) k=i;ans.A[t][mid]=x.A[t][k]+d2[y.l][k]+y.A[k][mid];if (l==r) return;Solve(x,y,t,l,mid,L,k);Solve(x,y,t,mid+1,r,k,R);}Matrix Merge(Matrix &x,Matrix &y){  ans.clear(x.l,y.r);for (int i=1;i<=m;i++) Solve(x,y,i,1,m,1,m);return ans;}void up(int x) { tree[x]=Merge(tree[x<<1],tree[x<<1|1]); }void build(int x,int l,int r){if (r-l<=20) { tree[x].rebuild(l,r); return; }int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);up(x);}void change(int x,int l,int r,int y){if (r-l<=20) { tree[x].rebuild(l,r); return; }int mid=(l+r)>>1;if (y<=mid) change(x<<1,l,mid,y);else change(x<<1|1,mid+1,r,y);up(x);}
} segment;int main()
{n=read(),m=read();for (int i=1;i<=n;i++)for (int j=2;j<=m;j++) d1[i][j]=read(),s[i][j]=s[i][j-1]+d1[i][j];for (int i=2;i<=n;i++)for (int j=1;j<=m;j++) d2[i][j]=read();segment.build(1,1,n);int Case=read();while (Case--){int opt=read();if (opt==1) { int x=read()+1,y=read()+2;d1[x][y]=read();  for (;y<=m;y++) s[x][y]=s[x][y-1]+d1[x][y];segment.change(1,1,n,x);}else if (opt==2) {int x=read()+2,y=read()+1;d2[x][y]=read(),segment.change(1,1,n,x);}else printf("%d\n",segment.tree[1].A[read()+1][read()+1]);}return 0;
}

LuoguP5897 [IOI2013]wombats相关推荐

  1. [IOI2013]wombats(网格图分治+线段树+决策单调性)

    洛谷题目传送门 老话说的好,看见网格图,就想分治 我们对行进行分治 设当前分支节点是k,区间是 l [ k ] l[k] l[k]行到 r [ k ] r[k] r[k]行,他的分治子节点分别是 l ...

  2. node和npm是什么_什么是npm? 面向初学者的Node Package Manager教程

    node和npm是什么 This article should serve as an all-in-one essential guide for Node.js' favorite sidekic ...

  3. 全国计算机大赛获奖奖品,国内含金量高的竞赛证书全汇总

    国内含金量高的竞赛证书全汇总 来源:石家庄新闻网 2017-11-17 14:28:50 国内多数地区小升初.初升高及高校自主招生中认可的竞赛证书汇总如下: 一.语文学科及作文竞赛 1.奥林匹克杯全国 ...

  4. 2019.4.summary

    2019.4.1 BZOJ1061: [Noi2008]志愿者招募 真心有点难QAQ https://www.byvoid.com/zhs/blog/noi-2008-employee 看void爷的 ...

  5. bluej 编程_BlueJ和Greenfoot:学习Java的最佳IDE

    bluej 编程 您说您想学习Java. 它可能是一种令人生畏的语言. 如果您是一名新程序员,这甚至似乎是不可渗透的. 但是,您深吸一口气,决心下定决心. 好的,首先要做的是:您需要已经阅读过的那些集 ...

  6. 清华大学 计算机科学理论,高一被清华姚班录取,一个网瘾少年到理论计算机科学家的蜕变...

    当陈立杰站在清华大学特奖答辩的讲台上时,无数目光注视着他.前方是理论计算机科学家的坦途,而过去则是重度网瘾少年的曾经.他在旁人看来不可及的人生,只是一个普通人不普通的蜕变. 网瘾少年 从小学开始,陈立 ...

  7. 前端之样式化链接、web字体

    前端之样式化链接 链接 链接状态 默认样式 应用样式 在链接后插入外部链接图标 将链接样式化为按钮 Web字体 查找字体 免费的字体经销商 在线字体服务 Web 字体 使用下载字体(第一次用) 我下载 ...

  8. 《Python自然语言处理-雅兰·萨纳卡(Jalaj Thanaki)》学习笔记:04 预处理

    03 预处理 4.1 处理原始语料库文本 4.1.1 获取原始文本 4.1.2 小写化转换 4.1.3 分句 4.1.4 原始文本词干提取 4.1.5 原始文本词形还原 4.1.6 停用词去除 4.2 ...

  9. 【CSS】样式化文字

    根据MDN网站学习记录笔记 样式化文字 基本文本和字体样式 字体种类 字体样式.字体粗细 文本转换.文本装饰 文字阴影 文本布局 样式列表 符号样式 项目符号位置 自定义项目符号图片 管理列表计数 样 ...

最新文章

  1. [c#基础]ICloneable接口
  2. Netty Pipeline源码分析(2)
  3. jps could not synchronize with target
  4. 大数据实战之环境搭建(七)
  5. 仿windows造字程序的 ASP.NET图片组合生成控件
  6. opencv cv2.LUT()(使用查找表中的值填充输出数组)
  7. ​电赛 | 19年全国一等奖,北航学子回忆录(上)
  8. android studio 分页,Android Paging codelab
  9. docker 容器命令
  10. 003.linux开发环境配置及linux极速入门
  11. 【动态规划】状压dp:蓝桥2020补给(旅行商问题)
  12. 故事的小黄花,从CSDN那年就飘着
  13. 水晶报表-推拉模式实例
  14. 根据输入时间判断年龄是否在18~68周岁之间
  15. 技术分析淘宝的超卖宝贝
  16. 打卡1 谭浩强c语言程序设计第三章
  17. web前端开发实训报告,HTML表单标签
  18. CSS背景颜色之奇技淫巧
  19. 淦!为什么到处都是广告!
  20. linux dd 克隆很慢,使用dd命令进行SD卡克隆

热门文章

  1. 难以摸透的直男脑回路......
  2. 酒桌上,领导将酒泼到你脸上......
  3. Python到底是有什么魅力,让程序猿为它折腰?
  4. 一堂儿童科学实验课引起的思考:数学和化学有什么关系?
  5. 我敢打赌,这世界没有python数据分析解决不了的问题
  6. php返回一个变量,PHP从另一个文件获取变量
  7. java对象头_我的并发编程(二):java对象头以及synchronized升级过程
  8. 我丢,去面试初级Java开发岗位,被问到泛型?
  9. oracle体系结构和组件图示,Oracle 体系结构组件
  10. 公众号滑动图代码_实用技巧:公众号封面图如何提取?