Solution

考虑从\((x_1,y_1)\)走到\((x_2,y_2)\)满足只改变一次方向,则容易求出先向南走当且仅当

\[\frac{a_{x_1} - a_{x_2}}{x_1 - x_2}<\frac{b_{x_1} - b_{x_2}}{x_1 - x_2}
\]

我们思考,没有用的行或列满足什么条件。

以行为例,考虑有三行:\(x=i, x=j,x=k\),两列:\(y=l,y=r\),从\((i,l)\)走到\((k,r)\)我们的条件是在\(x=j\)上走过一定更劣,故而能将\(x=j\)删去

假设我们从经\(x=j\)走到了,那么可以得到

\[\frac{a_{i} - a_{j}}{i - j}<\frac{b_{l} - b_{r}}{l - r}
\]

到这里有一个比较容易想到的构造:若

\[\frac{a_{i} - a_{j}}{i - j}>\frac{a_{j} - a_{k}}{j - k}
\]

则不会从\((j,l)\)经过\(x=j\)走到\((k,r)\)

所以我们要对\((i,a_i)\)维护出一个斜率单调递增的凸包,那么在凸包上的行就是可能有用的

对于列,同理

然后呢?如何求答案?

需要注意的是,在求答案的时候不能一次跳一个矩形的两条边,因为我们上面的条件是在只改变一次方向的情况下的,正确的方式是在\((x,y)\)的位置通过比较开头的式子,来决定先往哪个方向走,但是只走一段,因为通过去掉重复的部分可以发现走出的每一步都需要依赖于开头的式子,而走出一步后,状态发生改变,所以要重新找出最优决策。可以通过维护两个指针实现,复杂度\(O(H+W)\)

Code

#include <cstdio>
#include <iostream>
#define LL long long
using namespace std;
inline LL read() {
LL res = 0, f = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
if(f) res = ~res + 1;
return res;
}
const int N = 1000100;
LL h, w, a[N], b[N], ans, stk[N], top, p[N], q[N];
inline double slope1(LL x, LL y) {return 1.0 * (a[x] - a[y]) / (x - y);}
inline double slope2(LL x, LL y) {return 1.0 * (b[x] - b[y]) / (x - y);}
inline LL calc(LL x, LL y, LL nx, LL ny) {
if(x == nx) return a[x] * (ny - y);
else return b[y] * (nx - x);
}
int main() {
h = read(), w = read();
for(int i = 1; i <= h; ++i) a[i] = read();
for(int i = 1; i <= w; ++i) b[i] = read();
for(int i = 1; i <= h; ++i) {
while(top > 1 && slope1(i, stk[top - 1]) < slope1(stk[top], stk[top - 1])) --top;
stk[++top] = i;
}
for(int i = 1; i <= top; ++i) p[i] = stk[i];
top = 0;
for(int i = 1; i <= w; ++i) {
while(top > 1 && slope2(i, stk[top - 1]) < slope2(stk[top], stk[top - 1])) --top;
stk[++top] = i;
}
for(int i = 1; i <= top; ++i) q[i] = stk[i];
for(int p1 = 1, p2 = 1, x = 1, y = 1; !(x == h && y == w); ) {
if(x == h) ans += calc(x, y, x, q[++p2]), y = q[p2];
else if(y == w) ans += calc(x, y, p[++p1], y), x = p[p1];
else {
if(slope1(p[p1], p[p1 + 1]) < slope2(q[p2], q[p2 + 1])) ans += calc(x, y, p[++p1], y), x = p[p1];
else ans += calc(x, y, x, q[++p2]), y = q[p2];
}
}
printf("%lld\n",ans);
}

「JOISC 2022 Day1」京都观光 题解的更多相关文章

  1. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  2. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  3. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  4. 「JOISC 2014 Day1」巴士走读

    「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...

  5. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

  6. 「题解」「JOISC 2014 Day1」历史研究

    目录 题目 考场思考 思路分析及标程 题目 点这里 考场思考 大概是标准的莫队吧,离散之后来一个线段树加莫队就可以了. 时间复杂度 \(\mathcal O(n\sqrt n\log n)\) . 然 ...

  7. 「JOISC 2014 Day1」历史研究 --- 回滚莫队

    题目又臭又长,但其实题意很简单. 给出一个长度为\(N\)的序列与\(Q\)个询问,每个询问都对应原序列中的一个区间.对于每个查询的区间,设数\(X_{i}\)在此区间出现的次数为\(Sum_{X_{ ...

  8. 「JOISC 2020 Day1」汉堡肉

    我终于学会打开机房的LOJ了! description LOJ3272 有\(n(n<=2*10^5)\)个矩形,让你找\(k(k<=4)\)个点可以覆盖所有矩形(点可重复),输出一种方案 ...

  9. 「JOISC 2019 Day3」穿越时空 Bitaro

    「JOISC 2019 Day3」穿越时空 Bitaro 题解: ​ 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. ​ 问题变成二维平面上 ...

随机推荐

  1. PhoneBean实体类的封装和map输出键值对的设置

    之前我们写好了bean类型.现在我们再看看这个需求中,map和reduce各自的流程. Map阶段: 字段切分以后保留如下字段:以第一行为例,就保留13726230503112  2481 24681 ...

  2. MYSQL常见可优化场景

    1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null 可以在num上设置 ...

  3. 如何给MySQL添加自定义语法 ?

    目录 1 背景 2 新增关键词(token) 3 新增语法 4 类似于PT_partition添加对应的数据结构global_partition_clause 1 背景 MySQL语法解析器用的bis ...

  4. ViewPlane类定义

    这个类主要是记录了所有跟视图窗口有关的数据,用于显示. 类声明: #pragma once #ifndef __VIEWPLANE_HEADER__ #define __VIEWPLANE_HEADE ...

  5. 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(10)-Fiddler如何设置捕获Firefox浏览器的Https会话

    1.简介 经过上一篇对Fiddler的配置后,绝大多数的Https的会话,我们可以成功捕获抓取到,但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话,需要我们更进一步的配置才能捕获到会 ...

  6. JavaScript的入门

    书写的三种方式 1. 书写在script标签里面(一般会用到的) 2.书写在js文件里面(推荐)定义一个js文件(xxx.js) 3. 书写对应的事件属性里面(比较少用) 初体验 1. 目前js的代码 ...

  7. CF165D Beard Graph(dfs序+树状数组)

    题面 题解 乍一看,单点修改,单链查询,用树链剖分维护每条链上白边的数量就完了, 还是--得写树链剖分吗?--3e5,乘两个log会T吗-- (双手颤抖) (纠结) 不!绝不写树链剖分! 这题如果能维 ...

  8. AtCoder Beginner Contest 255(E-F)

    Aising Programming Contest 2022(AtCoder Beginner Contest 255) - AtCoder E - Lucky Numbers 题意: 给两个数组a ...

  9. DispatcherServlet 分发流程

    0 太长不看版 HTTPServlet 的 Service 方法将请求按类进行分解 主要是根据HTTP方法的类型调用 doXXX 方法 GET 和 HEAD 方法需要对 if-modified-sin ...

  10. php统计IP PV和今日访问量统计方法

    php引用,在wordpress主题中 $getroot=$_SERVER['DOCUMENT_ROOT']; require_once("$getroot/countstart.php&q ...