【NOIP2012-开车旅行】
这道题:你不仅要学会两人交换开车,还要做到高效驾驶。
·分析:
在拨开花哨题目的迷雾之后,发现两个重要突破口:
①从每个点开始,他们的路径是一定的,不存在决策选取。
②要是n,m没有那么大的话,就直接预处理每个点对于每个人开车至下一个点的位置和路程(n2),然后两个问题都可以从起点(第一问就是枚举起点)开始预处理的数据来“轮流开车”。(这一个突破口有点过于顶尖了,因为这是过70%数据的题解)
下图是这种做法的简图。
用des[i][0],des[i][1]分别表示在城市i小B开车和小A开车前往的下一个目的地。用Min[i][0],Min[i][1]分别与上面的数组对应,表示对应路径的长度(注意是反向枚举)
·无论是第一问还是第二问,都可以从起点s开始,通过des,Min数组来向后开车并记录两人各自走的路程。
·很美妙但又很遗憾,仅仅这样做时间复杂度:(n2+nm)
·这道题真正的考点就出来了:考察我们的优化技能。
·很轻易可以发现,这道题的数据范围又给了我们很大的提示:
n<=100000。这启示我们:nlogn
·余下的事情就是把时间复杂度中的部分n替换成logn,使得时间复杂度保持在:O(mlogn+nlogn)【这有点过于顶尖了】
·在本题中大米饼的对策是:预处理des,Min(这原来是一个n2)时使用STL中的set来维护(降为nlogn),在路径上使用倍增法,
·最后一个值得注意的一点,倍增的每一段为了方便操作,这里AB各走一次算成一段,不过倍增的距离还是对AB进项单独维护。整个程序还有许多细节需要注意。 wow!
#include<stdio.h>
#include<algorithm>
#include<set>
#define go(i,a,b) for(int i=a;i<=b;i++)
#define ro(i,a,b) for(int i=a;i>=b;i--)
#define inf 2147483645
#define eps 0.000003
using namespace std;const int N=;
int n,m,s,h[N],des[N][],Min[N][],To[N][],dis[N][][],tot[],x;
struct info{int h,id;bool operator<(const info a)const{return h<a.h;};};
set<info>box;set<info>::iterator I;int A(int t){return t<?-t:t;}
void consider(int i,info p)
{
int j=p.id;
if((A(h[i]-h[j])<Min[i][])||(Min[i][]==A(h[i]-h[j])&&h[j]<h[des[i][]]))
{
if((Min[i][]<Min[i][])||(Min[i][]==Min[i][]&&h[des[i][]]<h[des[i][]]))
Min[i][]=Min[i][],des[i][]=des[i][];
Min[i][]=A(h[i]-h[j]),des[i][]=j;
}
else if((A(h[i]-h[j])<Min[i][])||(Min[i][]==A(h[i]-h[j])&&h[j]<h[des[i][]]))
Min[i][]=A(h[i]-h[j]),des[i][]=j;
}
void doubling(int i,int val)
{
ro(k,,)if(dis[i][k][]+dis[i][k][]<=val&&To[i][k])
val-=(dis[i][k][]+dis[i][k][]),
tot[]+=dis[i][k][],tot[]+=dis[i][k][],i=To[i][k];
if(des[i][]&&Min[i][]<=val)tot[]+=Min[i][];
}
int main(){scanf("%d",&n);go(i,,n)scanf("%d",&h[i]),Min[i][]=Min[i][]=inf;
ro(i,n,)
{
box.insert((info){h[i],i});
I=box.find((info){h[i],i});++I;
if(I!=box.end())consider(i,*I),++I,I!=box.end()?consider(i,*I),:,--I;--I;
if(I!=box.begin())--I,consider(i,*I),I!=box.begin()?--I,consider(i,*I),:;
} go(i,,n)To[i][]=des[des[i][]][],
dis[i][][]=Min[i][],dis[i][][]=Min[des[i][]][]; go(k,,)go(i,,n)To[i][k]=To[To[i][k-]][k-],
dis[i][k][]=dis[i][k-][]+dis[To[i][k-]][k-][],
dis[i][k][]=dis[i][k-][]+dis[To[i][k-]][k-][]; scanf("%d",&x);double rate=inf;int pos=;h[]=-inf;go(i,,n)
{
tot[]=tot[]=;doubling(i,x);double tmp=tot[]?1.0*tot[]/tot[]:inf;
if(tmp-rate<eps&&tmp-rate>-eps&&h[i]>h[pos])pos=i;
if(rate-tmp>eps)pos=i,rate=tmp;
} printf("%d\n",pos);scanf("%d",&m);go(i,,m)
{
scanf("%d%d",&s,&x);
tot[]=tot[]=;doubling(s,x);
printf("%d %d\n",tot[],tot[]);
}
return ;
}//Paul_Guderian
只许集中,不许分散。————海因茨·威廉·古德里安
【NOIP2012-开车旅行】的更多相关文章
- Cogs 1264. [NOIP2012] 开车旅行(70分 暴力)
1264. [NOIP2012] 开车旅行 ★★☆ 输入文件:drive.in 输出文件:drive.out 简单对比时间限制:2 s 内存限制:128 MB [题目描述] 小A 和小 ...
- P1081 [NOIP2012]开车旅行[倍增]
P1081 开车旅行 题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...
- noip2012开车旅行 题解
题目大意: 给出n个排成一行的城市,每个城市有一个不同的海拔.定义两个城市间的距离等于他们的高度差的绝对值,且绝对值相等的时候海拔低的距离近.有两个人轮流开车,从左往右走.A每次都选最近的,B每次都选 ...
- NOIP2012开车旅行 【倍增】
题目 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城 ...
- Luogu 1081 [NOIP2012] 开车旅行
感谢$LOJ$的数据让我调掉此题. 这道题的难点真的是预处理啊…… 首先我们预处理出小$A$和小$B$在每一个城市的时候会走向哪一个城市$ga_i$和$gb_i$,我们有链表和平衡树可以解决这个问题( ...
- noip2012 开车旅行
此题100分的解法就是先预处理出每个点的下一个点之后倍增就好了.其实并没有太大难度. pbihao用双向链表写过了此题.在本地上我treap狂操他,but在rqnoj上,我依靠反复提交才A掉此题(最后 ...
- Luogu1081 NOIP2012 开车旅行 倍增
题目传送门 为什么NOIP的题目都这么长qwq 话说2012的D1T3和D2T3都是大火题啊qwq 预处理神题 对于这种跳跳跳的题目考虑使用倍增优化枚举.先预处理某个点之后距离最小和次小的城市,然后倍 ...
- luogu1081 [NOIp2012]开车旅行 (STL::multiset+倍增)
先用不管什么方法求出来从每个点出发,A走到哪.B走到哪(我写了一个很沙雕的STL) 然后把每个点拆成两个点,分别表示A从这里出发和B从这里出发,然后连边是要A连到B.B连到A.边长就是这次走的路径长度 ...
- 洛谷1081 (NOIp2012) 开车旅行——倍增预处理
题目:https://www.luogu.org/problemnew/show/P1081 预处理从每个点开始a能走多少.b能走多少.可以像dp一样从后往前推. 但有X的限制.所以该数组可以变成倍增 ...
- Luogu 1081 【NOIP2012】开车旅行 (链表,倍增)
Luogu 1081 [NOIP2012]开车旅行 (链表,倍增) Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已 ...
随机推荐
- Django Haystack 全文检索与关键词高亮
Django Haystack 简介 django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr.Elasticsearch.Whoosh.Xapian 等多 ...
- iOS开发所有KeyboardType与图片对应展示
1.UIKeyboardTypeAlphabet 2.UIKeyboardTypeASCIICapable 3.UIKeyboardTypeDecimalPad 4.UIKeyboardTypeDe ...
- 16-TypeScript装饰器模式
在客户端脚本中,有一个类通常有一个方法需要执行一些操作,当我们需要扩展新功能,增加一些操作代码时,通常需要修改类中方法的代码,这种方式违背了开闭的原则. 装饰器模式可以动态的给类增加一些额外的职责.基 ...
- XML之XPath
1.在 XPath 中,有七种类型的节点:元素.属性.文本.命名空间.处理指令.注释以及文档节点(或称为根节点). 1.1 XPath 术语 节点(Node) 在 XPath 中,有七种类型的节点:元 ...
- leetcode算法:Trim a Binar Search Tree
Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that a ...
- python/零起点(一、字符串)
python/零起点(一.字符串) 字符串(str) 字符串是可迭代的 str()强制转成字符串类型 字符串是有序的,且不可变的数据类型. 字符串转换整型的案例: 1 name=['guobaoyua ...
- Java:Java 中会存在内存泄漏吗
理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因):然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致 ...
- Django:(博客系统)添加文章(中文)出现UnicodeEncodeError乱码
添加文章时出现了一个UnicodeEncodeError乱码问题 在添加文章时,抛出了异常: 解决方案,修改manage.py(添加import sys reload(sys) sys.setdefa ...
- 南京邮电大学java程序设计作业在线编程第三次作业
王利国的"Java语言程序设计第3次作业(2018)"详细 作业结果详细 总分:100 选择题得分:60 1. 设有如下定义语句: String s1="My cat& ...
- hdu4864 Task贪心好题
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4864 题目大意: 有n个机器,m个任务.每个机器至多能完成一个任务.对于每个机器,有一个最大运行时间 ...