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入门课程 第3章 Python变量和数据类型
第3章 Python变量和数据类型3-1 Python中数据类型计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形 ...
- 自己定义Application的未捕获异常处理
近期由于工作原因.进行Android应用开发时发现应用在出现类似空指针等异常时,抛出未被捕获的异常.Android系统有默认的未捕获异常处理器,默认行为是结束对应的线程,但并不会直接退出程序,并且在应 ...
- EasyDSS流媒体解决方案实现的实时数据统计报表、视频文件上传、点播、分享、集成代码等功能
之前的EasyDSS作为rtmp流媒体服务器自从推出就备受用户好评,随着用户的需求的变更产品自身的发展是必须的: 为了更好的用户体验和和功能的完善,我们在EasyDSS的基础上增添了服务器硬件数据报表 ...
- java实现数字的反转
例如有一个数字是:19911002,要求是,我要得到它的反转后的数:20011991 实现如下: static void reverse(int a) { int rs = 0; while (a & ...
- 说说JSON和JSONP,也许你会豁然开朗,含jQuery用例(转载)
前言: 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域 ...
- 3.11课·········C#类
String类:.Length 字符的长度,返回一个int类型的值 .Trim() 去掉开头以及结尾的空格.TrimStart() 去掉字符串开头的空格.TrimEnd() 去掉字符串后面的空格 .T ...
- 正确认识 DIV+CSS 概念
今天看到神采飞扬发表于前端观察的<DIV+CSS 请不要再忽悠人了>,讲的挺有深意的,尤其对于新手如何正确认识div,学习web标准,使用web标准建站应该有很大帮助.转载过来,共同分享. ...
- 签offer和签三方协议
一般来讲,签约分为两种:签offer和签三方协议.其中,前者对个人及企业的约束效力远不及后者.下面分别来介绍. 1.签offer offer一般是单位提供给你的一个录用意向,以合同的形式提供给你,要求 ...
- Oracle数据库设计规范建议
Oracle数据库设计规范建议 1 目的 本规范的主要目的是希望规范数据库设计,尽量提前避免由于数据库设计不当而产生的麻烦:同时好的规范,在执行的时候可以培养出好的习惯,好的习惯是软件质量的很好的保证 ...
- Codeforces 372B Counting Rectangles is Fun:dp套dp
题目链接:http://codeforces.com/problemset/problem/372/B 题意: 给你一个n*m的01矩阵(1 <= n,m <= 40). 然后有t组询问( ...