【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 编号,且编号较小的城市在编号较大的城市的西边,已 ...
随机推荐
- choose the max from numbers, use scanf and if else (v1:21.9.2017,v2:23.9.2017)
#include<stdio.h> int main(){ int a,b,c,max; printf("请输入一个数值: "); scanf("%d&quo ...
- 《javascript设计模式与开发实践》阅读笔记(13)—— 职责链模式
职责链模式 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 书里的订单的例子 假设我们负责一个售卖手机 ...
- python的模块和包
==模块== python语言的组织结构层次: 包->模块->代码文件->类->函数->代码块 什么是模块呢 可以把模块理解为一个代码文件的封装,这是比类更高一级的封装层 ...
- 解决SoapFault (looks like we got no XML document)问题
今天在调试项目的时候出现下面的错误信息: SoapFault looks like we got no XML document (D:\phpStudy\WWW\self.shop.xunmall. ...
- restful架构风格设计准则(五)用户认证和session管理
读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者! Authentication REST提倡无状态约束,这就要求:用户状态 ...
- Linux实战案例(4)CentOS清除用户登录记录和命令历史方法
CentOS清除用户登录记录和命令历史方法 清除登陆系统成功的记录[root@localhost root]# echo > /var/log/wtmp //此文件默认打开时乱码,可查到ip等信 ...
- HTML5的常用新特性你必须知道
HTML5的常用新特性你必须知道 1 新的 声明 HTML 有多个不同的版本,只有完全明白页面中使用的确切 HTML 版本,浏览器才能完全正确地显示出 HTML 页面.这就是 的用处. 不是 HTML ...
- spring1——IOC之原理
spring框架的核心是IOC和AOP. 控制反转--IOC是一种编程思想,在spring中指的是对象的装配和管理交给了spring容器.这样做的好处是降低了系统之间的偶合度,既调用者不用再去创建被调 ...
- Docker:云栖社区开源论题及Spark开源论题
https://yq.aliyun.com/topic/78?spm=5176.8290451.656547.7.rMYhAF https://yq.aliyun.com/activity/155?u ...
- POJ-1125 Stockbroker Grapevine---Floyd应用
题目链接: https://vjudge.net/problem/POJ-1125 题目大意: 股票经纪人要在一群人中散布一个谣言,而谣言只能在亲密的人中传递,题目各处了人与人之间的关系及传递谣言所用 ...