传送门

题目大意

有$n$个格子从左到右依次挨着,一开始有两枚棋子分布在$A,B$某一个或两个格子里,有$m$个操作,第$i$次操作要求你把其中一个棋子移到$X_i$上,移动一个棋子的代价是两个格子之间的距离,求移完所有棋子的代价之和的最小值。

题解

首先这题显然不能贪心,后面的要求会对当前的选择产生影响。

考虑朴素的$n^2$的$DP$,设$F_{i,k}$表示满足恰好前$i$个操作时,除了处在$X_i$处的棋子,另一个棋子处在$k$的格子处的代价。

那么转移很显然$F_{i+1,k}=F_{i,k}+|X_i-X_{i+1}|$。

特别的,有另一处转移$F_{i+1,X_i}=\min\{F_{i,j}+|j-X_{i+1}|\}$。

这个第二处转移中绝对值看起来非常碍眼,考虑将按照$j\leq X_i,j\geq X_i$的情况变成了两类。

不难发现

对于$j\leq X_i,F_{i+1,X_i}=\min\{F_{i,j}+X_{i+1}-j\}$

对于$j\geq X_i,F_{i+1,X_i}=\min\{F_{i,j}+j-X_{i+1}\}$

考虑用线段树维护$F_{i,j}-j,F_{i,j}+j$,每次第一处转移相当于全局加,第二种转移相当于取一个前缀或后缀的最小值,然后转移就是单点取$min$。

初始时,令$X_0=B,F_{0,A}=0$其余的$F=INF$,每次转移,每个点取$min$即可。

复杂度$O(m\log n)$。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 200020
#define INF 10000000000000ll
using namespace std;
namespace IO{
const int BS=(1<<20); char Buffer[BS],*HD,*TL;
char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
int read(){
int nm=0,fh=1; char cw=Getchar();
for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
}
using namespace IO;
int n,m,A,B,G[M]; LL maxn,p[M<<2][2],ans=INF;
void pushup(int x){
p[x][0]=min(p[x<<1][0],p[x<<1|1][0]);
p[x][1]=min(p[x<<1][1],p[x<<1|1][1]);
}
void build(int x,int l,int r){
if(l==r){
if(l==A) p[x][0]=-l,p[x][1]=l;
else p[x][0]=p[x][1]=INF; return;
}
int mid=((l+r)>>1); build(x<<1,l,mid);
build(x<<1|1,mid+1,r),pushup(x);
}
LL qry(int x,int l,int r,int L,int R,int kd){
if(r<L||R<l) return INF; if(L<=l&&r<=R) return p[x][kd];
int mid=((l+r)>>1); return min(qry(x<<1,l,mid,L,R,kd),qry(x<<1|1,mid+1,r,L,R,kd));
}
void mdf(int x,int l,int r,int pos,LL dt){
if(l==r){p[x][0]=min(p[x][0],dt-l),p[x][1]=min(p[x][1],dt+l);return;}
int mid=((l+r)>>1);if(pos<=mid) mdf(x<<1,l,mid,pos,dt);else mdf(x<<1|1,mid+1,r,pos,dt); pushup(x);
}
void dfs(int x,int l,int r){
if(l==r){ans=min(ans,p[x][0]+(LL)l);return;}
int mid=((l+r)>>1);dfs(x<<1,l,mid),dfs(x<<1|1,mid+1,r);
}
int main(){
n=read(),m=read(),A=read(),B=read(),G[0]=B,build(1,1,n);
for(int i=1;i<=m;i++){
G[i]=read(); LL t1=G[i]+qry(1,1,n,1,G[i],0)+maxn;
LL t2=qry(1,1,n,G[i],n,1)-G[i]+maxn,dt=abs(G[i]-G[i-1]);
maxn+=dt,mdf(1,1,n,G[i-1],min(t1,t2)-maxn);
} dfs(1,1,n),printf("%lld\n",maxn+ans); return 0;
}

Arc073_F Many Moves的更多相关文章

  1. [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 ...

  2. [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 ...

  3. LeetCode Minimum Moves to Equal Array Elements II

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

  4. LeetCode Minimum Moves to Equal Array Elements

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

  5. 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 ...

  6. Knight Moves

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

  7. HDU 1372 Knight Moves

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

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

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

  9. HDU 1372 Knight Moves (bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1372 Knight Moves Time Limit: 2000/1000 MS (Java/Othe ...

随机推荐

  1. 圆环自带动画进度条ColorfulRingProgressView

    这是项目中遇到了,我也是借鉴大神的, 下载地址:https://github.com/oooohuhu/ColorfulRingProgressView 我把它导入了github中了,里面有详细的使用 ...

  2. java拾遗3----XML解析(三) StAX PULL解析

    使用PULL方式解析XML: Pull是STAX的一个实现 StAX是The Streaming API for XML的缩写,一种利用拉模式解析(pull-parsing)XML文档的API StA ...

  3. 九度OJ 1184:二叉树遍历 (二叉树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3515 解决:1400 题目描述: 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储). 例如如下的 ...

  4. spider_action

    spider from mobile to mobile to mobile from selenium import webdriver from selenium.webdriver.chrome ...

  5. What Every Computer Scientist Should Know About Floating-Point Arithmetic

    http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

  6. Servlet学习笔记【1】--- 背景和基础知识(CGI、Web服务器发展史、Servlet简介、任务、继承结构)

    本文主要讲Servlet的基础知识和背景知识. 1 CGI简介 CGI(Common Gateway Interface 公共网关接口)是WWW技术中最重要的技术之一,有着不可替代的重要地位.CGI是 ...

  7. [APIO2008]免费道路

    [APIO2008]免费道路 BZOJ luogu 先把必须连的鹅卵石路连上,大于k条no solution 什么样的鹅卵石路(u,v)必须连?所有水泥路都连上仍然不能使u,v连通的必须连 补全到k条 ...

  8. [luogu3767]膜法

    [luogu3767]膜法 luogu 神仙题 线段树分治+带权并查集 把每个操作看成点 首先这个操作的结构是一棵树 你发现每个点的对它的子树产生影响 我们可以想到用dfn序把它转成一段区间用线段树分 ...

  9. 洛谷P3943 星空

    洛谷P3943 星空 题目背景 命运偷走如果只留下结果, 时间偷走初衷只留下了苦衷. 你来过,然后你走后,只留下星空. 题目描述 逃不掉的那一天还是来了,小 F 看着夜空发呆. 天上空荡荡的,没有一颗 ...

  10. spring bean实例化的三种方式

    一.使用类的无参构造创建 配置文件 java代码 注意若类里面没有无参的构造,则会出现异常 二.使用静态工厂创建 配置文件 java代码 Factory类 测试类 结果 三.使用实例工厂 配置文件 1 ...