乐滋滋在wc上讲的题

对于这类最优化问题,有一个套路是考虑答案的下界,然后判看能不能到达这个下界
首先一个显然的下界是 ∑|i−ai| ∑ | i − a i | \sum |i-ai| ,但注意到这个下界不够紧,比如序列 1 0 3 2,0和3之间的间隔至少要跨越2次
建一个图,每本书代表一个点,连出一条有向边到他要去的位置,这个的意思就是指这个图中边不相交的环之间的跨越可能要额外的花费

这样确定的下界对于出发点在1的情况是对的,为什么?手玩一下可以发现,如果环A包含/相交环B(A在左B在右),环A可以在走到环B左端的时候放下书拿起B的书,走完环B回到左端点再拿起A的书继续走,如图

这是一个环AB和环CD相交的情况,我们可以从A走到C,将手里的书和C的书交换,走到D换书,走回C换书,接着走AB的环,这样的花费是贴着下界的

这时一个环AB包含环CD的情况,同样,我们从A走到C换书,走完环CD回到C换书,继续环AB,同样也是贴着下界的

那么为什么出发点不在1的时候不一定对呢?因为1一定是在一个最外围的环,比如上图,如果出发点在环CD上,而环AB包含环CD,那么走的时候不能解决AB,需要支付额外的花费从出发点走到环AB上才能接着按下界走,易证这也是最优的方案,于是问题就变成了出发点走到任意一个最外围的环上的最短路,点i向i-1,i+1连边权为1的边,向同一个环内的相邻点连边权为0的边跑最短路,因为边权只有0/1,最短路可以用bfs,0边放队头1边放队尾O(n)跑

(代码有个地方莓findfa挂掉了,现在fix了…)
我的做法是用并查集合并所有相交的环,然后相邻的环连边权1,跑bfs最短路

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;inline void read(int &x)
{char c; while(!((c=getchar())>='0'&&c<='9'));x=c-'0';while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline void up(int &a,const int &b){if(a<b)a=b;}
inline void down(int &a,const int &b){if(a>b)a=b;}
const int maxn = 2100000;int n,c[maxn],S;
int okl[maxn],okr[maxn];
ll ans;int id[maxn],cnt,L[maxn],R[maxn],dep[maxn];
void mark(int x)
{while(!id[x]){id[x]=cnt; down(L[cnt],x); up(R[cnt],x); x=c[x];}
}
int fa[maxn];
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
int t[maxn],tp;struct edge{int y,nex;}a[maxn<<1]; int len,fir[maxn];
inline void ins(const int x,const int y){a[++len]=(edge){y,fir[x]};fir[x]=len;}
int dis[maxn];
queue<int>q;int main()
{//freopen("tmp.in","r",stdin);//read(n); read(S); ++S;for(int i=1;i<=n;i++) {read(c[i]); c[i]++;ans+=(ll)abs(i-c[i]);}for(int i=1;i<=n;i++) okl[i]=okl[i-1]|(c[i]!=i);for(int i=n;i>=1;i--) okr[i]=okr[i+1]|(c[i]!=i);for(int i=1;i<=n;i++) if(!id[i]) {++cnt,fa[cnt]=cnt; L[cnt]=R[cnt]=i;mark(i);}tp=0;for(int i=1;i<=n;i++){int ii=findfa(id[i]);if(i==L[ii]) t[++tp]=i;while(t[tp]>L[ii]){int la=t[tp--];int f1=findfa(ii),f2=findfa(id[la]);fa[f2]=f1; up(R[f1],R[f2]),down(L[f1],L[f2]);}if(i==R[ii]) tp--;}for(int i=1;i<=cnt;i++) findfa(i),dis[i]=n+1;for(int i=1,mxr=0;i<=n;i++){int ii=fa[id[i]]; if(mxr<i){dep[ii]=1;if(i<=S) ans+=okl[i-1]?2:0;else ans+=okr[i]?2:0;}up(mxr,R[ii]);}for(int i=1;i<=n;i++){int ii=fa[id[i]];if(i>1){int j=fa[id[i-1]]; if(ii!=j) ins(ii,j);}if(i<n){int j=fa[id[i+1]];if(ii!=j) ins(ii,j);}}S=fa[id[S]]; dis[S]=0,q.push(S);while(!q.empty()){const int x=q.front(); q.pop();for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(dis[y]>dis[x]+1)dis[y]=dis[x]+1,q.push(y);}int mn=n+1;for(int i=1;i<=cnt;i++) if(dep[i]) down(mn,dis[findfa(i)]);ans+=mn<<1;printf("%lld\n",ans);return 0;
}

IOI2017 古书books相关推荐

  1. Codeforces Round #699 (Div. 2) E.Sorting Books(贪心+DP / 线段树)超高质量题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 E - Sorting Books 一排书架上有 nnn 本书排成一排,每本书上有一个颜色 aia_i ...

  2. BOOKS STORE OPENCART 自适应主题模板 ABC-0093

    2019独角兽企业重金招聘Python工程师标准>>> BOOKS STORE OPENCART 自适应主题模板 ABC-0093 模板特性 兼容浏览器 FireFox 1.5-3. ...

  3. Error: No module named books

    http://djangobook.py3k.cn/2.0/chapter05/ 输入 python manage.py validate, 提示 No module named books 只要将s ...

  4. Free Download Top 100 Hacking Books

    2019独角兽企业重金招聘Python工程师标准>>> Kali Linux – Assuring Security by Penetration Testing Network A ...

  5. 推荐两本旧书 recommend two CM books,which are not up-to-date

    Recently, some person ask me some question about CM. I want to recommend two CM books,though they ar ...

  6. Sicily 6768. Log Books 解题报告

    题目传送门:6768. Log Books 思路: 1. 这道题比较麻烦的是输入,时间的格式如12:04 ,这样后面再计算加减的时候会有问题,所以干脆转化成分钟,没一个时刻用该时刻是当天的第多少分钟表 ...

  7. [Flask+Vue]Books全栈应用

    Flask和Vue.js构建全栈单页面web应用[通过Flask开发RESTful API] 路小飞 退乎(假的) ​关注 146 人赞同了该文章 前言: 看了一些国外的关于介绍flask和vue的前 ...

  8. CodeForces - 1481E Sorting Books(贪心+dp)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,每次操作可以将任意一本书放到序列的末尾,问最少需要操作多少次,才能使得相同的数字挨在一起 题目分析:不难看出,对每个位置的数都操作一次,是 ...

  9. Books Queries(codeforces 1066)

    You have got a shelf and want to put some books on it. You are given q queries of three types: L id ...

最新文章

  1. 【硅谷牛仔】当代钢铁侠-特斯拉CEO 埃隆·马斯克
  2. Linux下关机、重启
  3. Online Learning场景下实时新闻热点机器学习训练实践
  4. [云炬创业管理笔记]第三章打造优秀创业团队讨论1
  5. windows ssh远程登录阿里云遇到permissions are too open的错误
  6. arp 命令最简单的小应用
  7. 80% 的 Java 焦虑,都可以被这张图解决
  8. matlab 基础 —— 文本文件读取
  9. ATEN瞄准专业级影音市场,发表全新VanCryst™视频系列产品线
  10. 【A little interesting】LeetCode 437. Path Sum III
  11. 数据结构之二叉查找树
  12. 数据库原理mysql课堂超星尔雅_超星尔雅数据库原理网课答案
  13. 电脑端图纸设计辅助工具-AutoCAD提供下载
  14. MySQL数据备份恢复太慢解决办法
  15. iis 缓存 静态文件_强制更新IIS中的缓存JavaScript文件
  16. 如何把Word文档中的数字和字母变成新罗马字体?
  17. Android 自定义View UC下拉刷新效果(一)
  18. linux桌面网络连接是个X,Xbrowser如何运行多个X桌面
  19. 安卓:点击空白处隐藏软键盘
  20. Excel - 快速找出数据差异

热门文章

  1. Android Studio Gradle编译异常
  2. 中山大学计算机学院优势,中山大学四大王牌专业 优势学科有哪些
  3. 怎样恢复微信删除的聊天记录
  4. 直播电商源码如何实现开屏广告
  5. 西门子PLC常用通信协议以及常用协议的区别(一)
  6. Opencv-霍夫圆检测-代码解析
  7. 剑指offer 66道题目java实现全部代码
  8. 1905协议详解(一)概述
  9. GitHub入门与实践pdf
  10. yaml文件编写格式