题目大意:
  有一排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。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 typedef signed long long int int64;
  6 inline unsigned getint() {
  7     register char ch;
  8     while(!isdigit(ch=getchar()));
  9     register unsigned x=ch^'0';
 10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 11     return x;
 12 }
 13 inline int64 min(const int64 &a,const int64 &b) {
 14     return a<b?a:b;
 15 }
 16 const int64 inf=0x7ffffffffffffff;
 17 const int N=200001;
 18 int n;
 19 class FenwickTree {
 20     private:
 21         int64 val[N];
 22         int lowbit(const int &x) const {
 23             return x&-x;
 24         }
 25     public:
 26         FenwickTree() {
 27             std::fill(&val[0],&val[N],inf);
 28         }
 29         void modify(int p,const int64 &x) {
 30             while(p<=n) {
 31                 if(x<val[p]) {
 32                     val[p]=x;
 33                 } else {
 34                     return;
 35                 }
 36                 p+=lowbit(p);
 37             }
 38         }
 39         int64 query(int p) const {
 40             int64 ret=inf;
 41             while(p) {
 42                 ret=min(ret,val[p]);
 43                 p-=lowbit(p);
 44             }
 45             return ret;
 46         }
 47 };
 48 FenwickTree ta;
 49 class RevFenwickTree {
 50     private:
 51         int64 val[N];
 52         int lowbit(const int &x) const {
 53             return x&-x;
 54         }
 55     public:
 56         RevFenwickTree() {
 57             std::fill(&val[0],&val[N],inf);
 58         }
 59         void modify(int p,const int64 &x) {
 60             while(p) {
 61                 if(x<val[p]) {
 62                     val[p]=x;
 63                 } else {
 64                     return;
 65                 }
 66                 p-=lowbit(p);
 67             }
 68         }
 69         int64 query(int p) const {
 70             int64 ret=inf;
 71             while(p<=n) {
 72                 ret=min(ret,val[p]);
 73                 p+=lowbit(p);
 74             }
 75             return ret;
 76         }
 77 };
 78 RevFenwickTree tb;
 79 int64 f[N];
 80 inline void modify(const int &p,const int64 x) {
 81     if(x<f[p]) {
 82         f[p]=x;
 83         ta.modify(p,x-p);
 84         tb.modify(p,x+p);
 85     }
 86 }
 87 int main() {
 88     n=getint();
 89     int q=getint(),a=getint(),b=getint();
 90     std::fill(&f[0],&f[N],inf);
 91     modify(a,0);
 92     int64 sum=0;
 93     while(q--) {
 94         a=b;
 95         b=getint();
 96         sum+=abs(a-b);
 97         int64 t1=ta.query(b)+b,t2=tb.query(b)-b;
 98         modify(a,min(t1,t2)-abs(a-b));
 99     }
100     int64 tmp=inf;
101     for(register int i=1;i<=n;i++) {
102         tmp=min(tmp,f[i]);
103     }
104     printf("%lld\n",tmp+sum);
105     return 0;
106 }

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

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<cstdlib>
 5 inline unsigned getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register unsigned x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 inline unsigned min(const unsigned &a,const unsigned &b) {
13     return a<b?a:b;
14 }
15 const unsigned N=200000;
16 unsigned long long f[2][N];
17 unsigned a[2];
18 int main() {
19     unsigned n=getint(),q=getint();
20     memset(f[0],0xff,n<<3);
21     a[0]=getint()-1,f[0][getint()-1]=0;
22     for(register unsigned i=1;i<=q;i++) {
23         a[i&1]=getint()-1;
24         memset(f[i&1],0xff,n<<3);
25         for(register unsigned j=0;j<n;j++) {
26             if(!~f[~i&1][j]) continue;
27             f[i&1][j]=min(f[i&1][j],f[~i&1][j]+abs(a[i&1]-a[~i&1]));
28             f[i&1][a[~i&1]]=min(f[i&1][a[~i&1]],f[~i&1][j]+abs(a[i&1]-j));
29         }
30     }
31     unsigned long long ans=~0;
32     for(register unsigned i=0;i<n;i++) {
33         ans=min(ans,f[q&1][i]);
34     }
35     printf("%llu\n",ans);
36     return 0;
37 }

View Code

转载于:https://www.cnblogs.com/skylee03/p/7609824.html

[AtCoder-ARC073F]Many Moves相关推荐

  1. arc073F Many Moves

    题目链接 https://arc073.contest.atcoder.jp/tasks/arc073_d 题意简述 有nnn个格子,有两颗棋子,初始位置为A,BA,BA,B,移动一颗棋子从XXX到Y ...

  2. 退役前的做题记录5.0

    退役前的做题记录5.0 出于某种原因新开了一篇. [CodeChef]Querying on a Grid 对序列建立分治结构,每次处理\((l,mid,r)\)时,以\(mid\)为源点建立最短路树 ...

  3. AtCoder题解 —— AtCoder Beginner Contest 182 —— D - Wandering

    题目相关 题目链接 AtCoder Beginner Contest 182 D 题,https://atcoder.jp/contests/abc182/tasks/abc182_d. Proble ...

  4. [Educational Codeforces Round 16]A. King Moves

    [Educational Codeforces Round 16]A. King Moves 试题描述 The only king stands on the standard chess board ...

  5. poj - 2243 Knight Moves

    这题和poj 1915一样,用bfs做走马步.现在再看当时的代码,真是好幼稚啊. 1 #include <stdio.h> 2 #include <string.h> 3 in ...

  6. ICPC / CCPC / Codeforces / AtCoder 单词本

    过不了六级的小菜鸡呜呜呜,好久没有背过单词了,都忘完了 放一些写ICPC真题 / CCPC真题 / Codeforces / AtCoder 的时候不能立刻反应过来的单词每天背一下 四舍五入 roun ...

  7. 【每日亿题#12】AtCoder Grand Contest 021 (A ~ F)全部题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 文章目录 AtCoder Grand Contest 021 题解 A. Digit Sum 2 B. ...

  8. AtCoder Beginner Contest 202 D - aab aba baa(组合计数,字典序)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 有 AAA 和 aaa,BBB 个 bbb ,可以使用这 A+BA+BA+B 个字符任 ...

  9. AtCoder Beginner Contest 197 题解(A ~ F)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A - Rotate B - Visibility C - ORXOR D - Opposite ...

  10. AtCoder Beginner Contest 198 (A ~ F)题解

    目录 A. Div B. Palindrome with leading zeros C. Compass Walking D. Send More Money E. Unique Color F. ...

最新文章

  1. 王家豪:求实探索,青春无问西东;脚踏实地,奋斗自成芳华 | 提升之路系列...
  2. JAVA关于父亲节的代码_关于父亲节的经典语录
  3. 频谱仪使用方法图解_地暖分水器原理及使用方法介绍,图解
  4. codeforces 869C The Intriguing Obsession 组合数学,逆元
  5. 官宣预热iQOO 7强悍配置:“性能铁三角”加持 给你强悍全感
  6. 荣耀鸿蒙os2.0公测版,鸿蒙OS 2.0他来了!华为HarmonyOS 2.0开发者公测版正式推送
  7. 多线程的那点儿事(之优先级反转)
  8. python实现播放音乐_python实现简易云音乐播放器
  9. linux运行库,Linux C 静态库 共享库 运行库
  10. 微信 小程序 python 渲染_干货 | 微信小程序自动化测试最佳实践(附 Python 源码)...
  11. 利用第三方rec解锁安卓手机锁屏密码
  12. 2020FME博客大赛——基于FME的海量数据点高效率抽稀技术及实现
  13. cad怎样弄出放线的坐标_不知道如何定位放线?今天教大家一个快速准确放线方法(含实例)...
  14. UIControl 详解
  15. 1001. 会议安排
  16. Facet Kernel详解、Random Walk随机游走算法详解
  17. 如何利用ArcGIS制效果较好的DEM渲染图
  18. 图形学的三种拾取实现与比较
  19. Android Activity 降低屏幕亮度 Android开发
  20. 干货满满【JVM监控及诊断工具-GUI篇】

热门文章

  1. linux mysql 存储过程乱码,mysql存储过程中 乱码问题解决办法
  2. switch()语句块的出口:break;
  3. 云测试软件详解,软件测试之登录测试详解
  4. java上传excel文件代码,求java把上传文件的excel表中数据存入数据库中.实现录入的代码?...
  5. mysql vim 命令_Vim基本命令必知必会
  6. asyncio oracle 异步,带有asyncio futures和RuntimeError的InvalidStateError与aiohttp时使用期货回调...
  7. JAVA数组扁平化整合_5种方法实现数组扁平化
  8. boot lvm 分区_Linux如何在线对逻辑分区扩容
  9. 计算机综合应用能力试题,计算机综合应用能力实训
  10. esp8266接7735_基于8266的ESPEASY固件接入HASS的教程(可无脑接入各类传感...