Arc073_F Many Moves
题目大意
有$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的更多相关文章
- [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 ...
- [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 ...
- LeetCode Minimum Moves to Equal Array Elements II
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/ 题目: Given a non-empt ...
- LeetCode Minimum Moves to Equal Array Elements
原题链接在这里:https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 题目: Given a non-empty i ...
- 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 ...
- Knight Moves
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- HDU 1372 Knight Moves
最近在学习广搜 这道题同样是一道简单广搜题=0= 题意:(百度复制粘贴0.0) 题意:给出骑士的骑士位置和目标位置,计算骑士要走多少步 思路:首先要做这道题必须要理解国际象棋中骑士的走法,国际象棋中 ...
- [宽度优先搜索] HDU 1372 Knight Moves
Knight Moves Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...
- HDU 1372 Knight Moves (bfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1372 Knight Moves Time Limit: 2000/1000 MS (Java/Othe ...
随机推荐
- python pymysql安装
==================pymysql=================== 由于 MySQLdb 模块还不支持 Python3.x,所以 Python3.x 如果想连接MySQL需要安装 ...
- python 基础 9.12 索引
#/usr/bin/python #-*- coding:utf-8 -*- #@Time :2017/11/24 4:48 #@Auther :liuzhenchuan #@File :索引 ...
- 为system对象添加扩展方法
////扩展方法类:必须为非嵌套,非泛型的静态类 public static class DatetimeEx { //通过this声明扩展的类,这里给DateTime类扩展一个Show方法,只有一个 ...
- GPL 与 LGPL 扫盲
本文部分摘自评论:从射手QQ之争看开源许可证的选择 首先,开源并不代表放弃自身的权力,相反,开源软件之所以存在,正是它非常注重这种权力,并且把这种权力赋予了软件的所有使用者.小心的选择许可证是开发开 ...
- 浅谈公平组合游戏IGC
浅谈公平组合游戏IGC IGC简介 一个游戏满足以下条件时被叫做IGC游戏 (前面三个字是自己YY的,不必在意) 竞争性:两名玩家交替行动. 公平性:游戏进程的任意时刻,可以执行的操作和操作者本人无关 ...
- JDBC【菜鸟学JAVA】
1:首先下载sqljdbc.jar,然后配置ClassPath,然后再在工程文件中把这个(sqljdbc.jar)架包引用上,就可以开始JAVA操作之旅了 打开Eclipse,“文件”→“新建”→“项 ...
- eclipse安装Activiti Designer插件(转载:http://blog.csdn.net/qq_33547950/article/details/54926435)
为了完成毕业设计,需要学习Activiti.万事开头难,果然刚开始就遇到了问题.<Activiti实战>和视频教程里提供的安装Activiti Designer插件方法(即下文方法一)不能 ...
- ThinkPHP 3.2.2 事务
手册里说得非常清楚 : 5.3.19 事务支持 ThinkPHP提供了单数据库的事务支持,如果要在应用逻辑中使用事务,可以参考下面的方法: 启动事务: PHP代码 $User->startTra ...
- 为jquery添加扩展标准思路
jquery扩展分为对象扩展和jquery本身类扩展: 对象扩展: (function($){ $.fn.abc = function(){ console.log($(this).get(0)); ...
- debian下蓝牙适配器的配置和使用
本文打算将蓝牙适配器和手机蓝牙进行配对. 买了个支持蓝牙4.0协议的蓝牙适配器,将其插入到pc(debian 7.4)的usb口. 查看手机蓝牙信息: 选择手机中"设置"-> ...