题目大意:有$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. jquer搜索

    <body> <br/> <center> <tr><td>创建时间:</td><td><input type ...

  2. python 函数 练习

    # 2.写函数,接收n个数字,求这些参数数字的和. def sum_func(*args): total = 0 for i in args: total += i return total prin ...

  3. C语言学习记录_2019.01.29

    C语言的灵魂:指针 #include <stdio.h> int main(int argc, char **argv) {  printf("Hello, World!\n&q ...

  4. codeblocks编译出错问题的解答!(编译c++ 或者c程序)

    典型错误:https://blog.csdn.net/jingmiaa/article/details/52054204 MinGW下载并配置gcc/g++编译环境:https://blog.csdn ...

  5. C++11中decltype的使用

    The decltype type specifier yields the type of a specified expression. The decltype type specifier, ...

  6. MySQL server has gone away 错误处理

    解决方案1: 这个是mysql自身的一个机制:     mysql连接的空闲时间超过8小时后 MySQL自动断开该连接解决办法有两个:     1.修改mysql 配置               增 ...

  7. abo dto属性验证的坑

    问题回现: public class ShipmentRequestDto { public string FromPhoneNumber { get; set; } /// <summary& ...

  8. K8s集群内热改代码

    1.登录到k8s master服务器 $ ssh developer@XXX.XXX.X.XXX(IP地址) 2.查看服务容器所在的节点(以xx-server为例) $ kubectl get pod ...

  9. QC的使用学习(一)

    今天学习的时间很少,就利用睡前的一点时间来学习一下刚安装好的QC. 1.后台站点管理.主要是对八大选项的了解: site project:顾名思义,就站点项目管理,管理域和项目. site user: ...

  10. 数据结构(python语言)目录链接

    第一章 准备工作 课时0:0.数据结构(python语言) 基本概念 算法的代价及度量!!!