题目大意:有$n$个位置$1,2,\dots n$;你有两个棋子$A$和$B$,你要进行$q$次操作,第$i$次操作给定一个$x_i$,你要选择一个棋子移动到$x_i$;求两个棋子最小移动的步数之和。

题解:一个$O(n^2)$的$DP$容易想到$f_{i,j}$表示到了第$i$步,另一个棋子在$j$这个位置。

$$f_{i,x_{i-1}}=\min\{f_{i-1,j}+|x_i-j|\}$$

$$f_{i,j}=f_{i-1,j}+|x_i-x_{i-1}|$$

下面一个还好做,可上面一个呢?

可以考虑拆成$j\leq x_i$和$j>x_i$来做

$$\therefore f_{i,x_{i-1}} =
\begin{cases}
f_{i-1,j}+x_i-j\quad(j\leq x_i)\\
f_{i-1,j}+j-x_i\quad(j>x_i)
\end{cases}$$

然后发现是区间修改求最小值,可以用线段树来做。

卡点:1.转移时把$x_{i-1}$写成了$x_{i}$

C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 200010
using namespace std;
const long long inf = 0x3f3f3f3f3f3f3f3f;
inline long long min(long long a, long long b) {return a < b ? a : b;}
inline long long abs(long long a) {return a > 0 ? a : -a;}
int n, k, x, y;
int q, last;
long long V[maxn << 2][3], cov[maxn << 2];
void pushdown(int rt) {
int lc = rt << 1, rc = rt << 1 | 1;
long long &tmp = cov[rt];
V[lc][0] += tmp;
V[lc][1] += tmp;
V[lc][2] += tmp;
cov[lc] += tmp;
V[rc][0] += tmp;
V[rc][1] += tmp;
V[rc][2] += tmp;
cov[rc] += tmp;
tmp = 0;
}
void update(int rt) {
int lc = rt << 1, rc = rt << 1 | 1;
V[rt][0] = min(V[lc][0], V[rc][0]);
V[rt][1] = min(V[lc][1], V[rc][1]);
V[rt][2] = min(V[lc][2], V[rc][2]);
}
void add(int rt, int l, int r, int p, long long num) {
if (l == r) {
V[rt][0] = num;
V[rt][1] = num + l;
V[rt][2] = num - l;
return ;
}
if (cov[rt]) pushdown(rt);
int mid = l + r >> 1;
if (p <= mid) add(rt << 1, l, mid, p, num);
else add(rt << 1 | 1, mid + 1, r, p, num);
update(rt);
}
void add(long long num, int rt = 1) {
V[rt][0] += num;
V[rt][1] += num;
V[rt][2] += num;
cov[rt] += num;
}
long long ask(int rt, int l, int r, int L, int R, int op) {
if (L <= l && R >= r) return V[rt][op];
pushdown(rt);
int mid = l + r >> 1;
long long ans = inf;
if (L <= mid) ans = ask(rt << 1, l, mid, L, R, op);
if (R > mid) ans = min(ans, ask(rt << 1 | 1, mid + 1, r, L, R, op));
return ans;
}
int main() {
scanf("%d%d%d%d", &n, &k, &x, &y);
scanf("%d", &q);
memset(V, 0x3f, sizeof V);
add(1, 1, n, x, abs(y - q));
add(1, 1, n, y, abs(x - q));
while (--k) {
last = q; scanf("%d", &q);
long long t0 = ask(1, 1, n, last, last, 0) + abs(q - last);
long long t1 = ask(1, 1, n, q, n, 1) - q;
long long t2 = ask(1, 1, n, 1, q, 2) + q;
long long ans = min(t0, min(t1, t2));
add(abs(q - last));
add(1, 1, n, last, ans);
}
printf("%lld\n", V[1][0]);
return 0;
}

  

[AT2558]Many Moves的更多相关文章

  1. AT2558 [ARC073D] Many Moves

    开始被标签带骗了. 考虑一个\(dp\),\(f[i][j]\)代表有一个棋子在\(x_i\),另外一个\(j\)的最小答案. 那么考虑转移. 如果\(j != x_{i - 1}\) 那么答案自然贡 ...

  2. [LeetCode] Minimum Moves to Equal Array Elements II 最少移动次数使数组元素相等之二

    Given a non-empty integer array, find the minimum number of moves required to make all array element ...

  3. [LeetCode] Minimum Moves to Equal Array Elements 最少移动次数使数组元素相等

    Given a non-empty integer array of size n, find the minimum number of moves required to make all arr ...

  4. LeetCode Minimum Moves to Equal Array Elements II

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...

  5. LeetCode Minimum Moves to Equal Array Elements

    原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...

  6. LeetCode 453 Minimum Moves to Equal Array Elements

    Problem: Given a non-empty integer array of size n, find the minimum number of moves required to mak ...

  7. Knight Moves

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  8. HDU 1372 Knight Moves

    最近在学习广搜  这道题同样是一道简单广搜题=0= 题意:(百度复制粘贴0.0) 题意:给出骑士的骑士位置和目标位置,计算骑士要走多少步 思路:首先要做这道题必须要理解国际象棋中骑士的走法,国际象棋中 ...

  9. [宽度优先搜索] HDU 1372 Knight Moves

    Knight Moves Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

随机推荐

  1. 构建ExtJS 6.x程序

    构建ExtJS 6.x程序 ExtJS也有自己的打包工具 SenchaCmd,它用来生成构建ExtJS前端组织架构,最后打包发布生产,操控着前端整个开发生命周期,SenchaCmd依赖于JDK,所以要 ...

  2. 网站标题被篡改成北京赛车、PK10的解决处理办法

    客户网站于近日被跳转到赌博网站,打开后直接跳转到什么北京赛车,PK10等内容的网站上去,客户网站本身做了百度的推广,导致所有访问用户都跳转到赌博网站上去,给客户带来很大的经济损失,再一个官方网站的形象 ...

  3. Python自动化运维——IP地址处理模块

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:IPy 功能:辅助我们高效的完成IP的规划工作 安装: wget https://pypi.python.o ...

  4. UVa Problem 100 The 3n+1 problem (3n+1 问题)

    参考:https://blog.csdn.net/metaphysis/article/details/6431937 #include <iostream> #include <c ...

  5. RedHat7.1 安装Oracle12102

    选型: 32位的内存是个瓶颈,已经是64位的时代了.使用64位的CentOS6 和 64位的Oracle 11g R2 在虚拟机器安装,采用hostonly方式设置网络 注意:能上网的网卡要设置一下I ...

  6. 教你如何更改xshell中的转发规则

    使用不同的类型转发,与之对应的端口,所以如果想要使用不同类型的转发就要更改端口使其与之一一对应.本集xshell专栏文章将为大家讲解如何更改转发规则. 更改转发规则操作如下: 1.打开会话对话框. 2 ...

  7. Java面试题集合

    1.Java的HashMap是如何工作的? HashMap是一个针对数据结构的键值,每个键都会有相应的值,关键是识别这样的值. HashMap 基于 hashing 原理,我们通过 put ()和 g ...

  8. HTML布局的元素

    header 定义文档或节的页眉 nav 定义导航链接的容器 section 定义文档中的节 article 定义独立的自包含文章 aside 定义内容之外的内容(比如侧栏) footer 定义文档或 ...

  9. 通过修改Host文件解决主机头访问网站的问题

             网站打包发布后,一般都是通过IP地址来进行访问,但是这样不方便记忆.如何设置一个简单的域名,然后通过域名来进行访问呢?一个可行的方法就是修改本机的host文件,添加一条映射关系,把这 ...

  10. (原)Android到IOS开发的转换(一)

    序)闲扯几句 很早就想入手ios开发,但是一直没有机会,个人没有水果机器,上个公司上班的那台mac mini虽然就在我身边,灰都有一层了,但是一直没有机会开机学习下,因为事多,自上一篇文章后,离职后, ...