题目大意:
  有一排n个格子和2枚硬币。
  现在有q次任务,每一次要你把其中一枚硬币移到x的位置上,移动1格的代价是1。
  两枚硬币不能同时移动,任务必须按次序完成。
  现在告诉你两枚硬币初始状态所在的位置a和b,问完成所有任务的最小代价。

思路:
  很容易想到一个O(qn)的DP。
  由于完成任务的次序确定,每个任务的位置也确定,我们可以用f[i][j]表示完成第i个任务后,一个硬币在x[i],一个硬币在j的最小代价。
  转移方程为f[i][j]=min{f[i-1][j]+|x[i]-x[i-1]|},f[i][a[i-1]]=min{f[i-1][j]+|x[i]-j|}。
  然而这样还是会TLE,在AtCoder上只过了14/34的测试数据。
  不难发现,在状态转移方程中,如果我们能去掉绝对值,里面的东西就能用线段树维护。
  而绝对值的取值只与硬币的左右位置关系有关。
  因此我们可以建2棵线段树,一棵表示被转移的状态在目标状态左边,一棵表示在右边。
  左线段树中每个叶子结点x[i-1]维护f[i-1][j]-x[i-1]的值,右线段树每个叶子结点x[i-1]维护f[i-1][j]+x[i-1]的值。
  看了一下榜,发现排在前面的基本上都是用树状数组做的。
  然而用树状数组维护区间最值难道不是O(log^2 n)的吗?
  事实上我们可以发现线段树上维护的东西只会越来越小,这样我们可以直接在树状数组上修改,不用考虑原来的最小值没了怎么办。
  然后我又在树状数组里面加了一个剪枝。
  这样随随便便就能拿Rank1。

 #include<cstdio>
#include<cctype>
#include<cstdlib>
#include<algorithm>
typedef signed long long int int64;
inline unsigned getint() {
register char ch;
while(!isdigit(ch=getchar()));
register unsigned x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
inline int64 min(const int64 &a,const int64 &b) {
return a<b?a:b;
}
const int64 inf=0x7ffffffffffffff;
const int N=;
int n;
class FenwickTree {
private:
int64 val[N];
int lowbit(const int &x) const {
return x&-x;
}
public:
FenwickTree() {
std::fill(&val[],&val[N],inf);
}
void modify(int p,const int64 &x) {
while(p<=n) {
if(x<val[p]) {
val[p]=x;
} else {
return;
}
p+=lowbit(p);
}
}
int64 query(int p) const {
int64 ret=inf;
while(p) {
ret=min(ret,val[p]);
p-=lowbit(p);
}
return ret;
}
};
FenwickTree ta;
class RevFenwickTree {
private:
int64 val[N];
int lowbit(const int &x) const {
return x&-x;
}
public:
RevFenwickTree() {
std::fill(&val[],&val[N],inf);
}
void modify(int p,const int64 &x) {
while(p) {
if(x<val[p]) {
val[p]=x;
} else {
return;
}
p-=lowbit(p);
}
}
int64 query(int p) const {
int64 ret=inf;
while(p<=n) {
ret=min(ret,val[p]);
p+=lowbit(p);
}
return ret;
}
};
RevFenwickTree tb;
int64 f[N];
inline void modify(const int &p,const int64 x) {
if(x<f[p]) {
f[p]=x;
ta.modify(p,x-p);
tb.modify(p,x+p);
}
}
int main() {
n=getint();
int q=getint(),a=getint(),b=getint();
std::fill(&f[],&f[N],inf);
modify(a,);
int64 sum=;
while(q--) {
a=b;
b=getint();
sum+=abs(a-b);
int64 t1=ta.query(b)+b,t2=tb.query(b)-b;
modify(a,min(t1,t2)-abs(a-b));
}
int64 tmp=inf;
for(register int i=;i<=n;i++) {
tmp=min(tmp,f[i]);
}
printf("%lld\n",tmp+sum);
return ;
}

原来的O(n^2)DP程序:

 #include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
inline unsigned getint() {
register char ch;
while(!isdigit(ch=getchar()));
register unsigned x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
inline unsigned min(const unsigned &a,const unsigned &b) {
return a<b?a:b;
}
const unsigned N=;
unsigned long long f[][N];
unsigned a[];
int main() {
unsigned n=getint(),q=getint();
memset(f[],0xff,n<<);
a[]=getint()-,f[][getint()-]=;
for(register unsigned i=;i<=q;i++) {
a[i&]=getint()-;
memset(f[i&],0xff,n<<);
for(register unsigned j=;j<n;j++) {
if(!~f[~i&][j]) continue;
f[i&][j]=min(f[i&][j],f[~i&][j]+abs(a[i&]-a[~i&]));
f[i&][a[~i&]]=min(f[i&][a[~i&]],f[~i&][j]+abs(a[i&]-j));
}
}
unsigned long long ans=~;
for(register unsigned i=;i<n;i++) {
ans=min(ans,f[q&][i]);
}
printf("%llu\n",ans);
return ;
}

[AtCoder-ARC073F]Many Moves的更多相关文章

  1. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

  2. 【arc073f】Many Moves(动态规划,线段树)

    [arc073f]Many Moves(动态规划,线段树) 题面 atcoder 洛谷 题解 设\(f[i][j]\)表示第一个棋子在\(i\),第二个棋子在\(j\)的最小移动代价. 发现在一次移动 ...

  3. 【ARC073F】Many Moves

    题目 一个显然的\(dp\),设\(dp_{i,j}\)表示其中一个棋子在\(x_i\)点,另一个棋子在\(j\)点的最小花费 显然\(dp_{i,j}\)有两种转移 第一种是把\(x_i\)上的棋子 ...

  4. [atcoder contest 010] F - Tree Game

    [atcoder contest 010] F - Tree Game Time limit : 2sec / Memory limit : 256MB Score : 1600 points Pro ...

  5. AtCoder Beginner Contest 151 题解报告

    总的来说,这次的题目比较水,然而菜菜的我并没有把所有题目都做完,话不多说,直接来干货: A:Next Alphabet 题目链接:https://atcoder.jp/contests/abc151/ ...

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

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

  8. LeetCode Minimum Moves to Equal Array Elements II

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

  9. LeetCode Minimum Moves to Equal Array Elements

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

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

随机推荐

  1. javascript中的数组去重

    1.方法一:双层循环,外层循环元素,内层循环做比较,若相同则跳过,不同则加入结果集中,获取没重复的最右侧的值放入数组中 Array.prototype.distinct = function(){ v ...

  2. Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式

    史诗级Java/JavaWeb学习资源免费分享 欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回 ...

  3. 2018 黑盾杯部分writeup

    这次比赛拿了三十多名.呵呵.或许这就是菜吧. 比赛经验教训: 1.赛前一定要调整好情绪. 2.比赛尽量不要紧张,每一题都认认真真的看过去! 3.站在出题者的角度去思考问题 4.刷题 5.还是情绪吧.其 ...

  4. discuz 积分按日重新计算,(摒弃以前24小时计算)

    修改\source\module\forum\forum_misc.php将 foreach(C::t('forum_ratelog')->fetch_all_sum_score($_G['ui ...

  5. rebbitmq之python_pika监控远程连接及自动恢复(七)

    前言 客户端连接rabbitmq后,如果长时间没有数据的传输,rabbitmq会申请关闭TCP连接,造成该TCP连接下的所有的信道都不可用,很多时候为了传输数据的高效率,我们会先创建一个信道池,这样省 ...

  6. 多个id或class属性相同的元素绑定事件

    <td class="tools"><a href="javascript:void(0);" status="0" na ...

  7. 如何读懂statspack报告

    前言:这篇文章是我从网上找到的,但可惜不知道是哪位大侠写(译)的,因此这里无法注明了.仔细看了看,这篇文章对初学者应该很有帮助,写的比较详细,通俗易懂,因此整理一下,便于阅读:内容略有调整,不单做调整 ...

  8. SVN的使用、分支合并及解决冲突详解

    一.什么是SVN SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS. 二.SVN的下载安装 下载地址:http ...

  9. Java显式锁学习总结之三:AbstractQueuedSynchronizer的实现原理

    概述 上一篇我们讲了AQS的使用,这一篇讲AQS的内部实现原理. 我们前面介绍了,AQS使用一个int变量state表示同步状态,使用一个隐式的FIFO同步队列(隐式队列就是并没有声明这样一个队列,只 ...

  10. POJ 3253 Fence Repair(哈夫曼编码)

    题目链接:http://poj.org/problem?id=3253 题目大意: 有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度 给定各个 ...