这道题:你不仅要学会两人交换开车,还要做到高效驾驶。

·分析:

      在拨开花哨题目的迷雾之后,发现两个重要突破口:

      ①从每个点开始,他们的路径是一定的,不存在决策选取。

      ②要是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-开车旅行】的更多相关文章

  1. Cogs 1264. [NOIP2012] 开车旅行(70分 暴力)

    1264. [NOIP2012] 开车旅行 ★★☆   输入文件:drive.in   输出文件:drive.out   简单对比时间限制:2 s   内存限制:128 MB [题目描述] 小A 和小 ...

  2. P1081 [NOIP2012]开车旅行[倍增]

    P1081 开车旅行    题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...

  3. noip2012开车旅行 题解

    题目大意: 给出n个排成一行的城市,每个城市有一个不同的海拔.定义两个城市间的距离等于他们的高度差的绝对值,且绝对值相等的时候海拔低的距离近.有两个人轮流开车,从左往右走.A每次都选最近的,B每次都选 ...

  4. NOIP2012开车旅行 【倍增】

    题目 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城 ...

  5. Luogu 1081 [NOIP2012] 开车旅行

    感谢$LOJ$的数据让我调掉此题. 这道题的难点真的是预处理啊…… 首先我们预处理出小$A$和小$B$在每一个城市的时候会走向哪一个城市$ga_i$和$gb_i$,我们有链表和平衡树可以解决这个问题( ...

  6. noip2012 开车旅行

    此题100分的解法就是先预处理出每个点的下一个点之后倍增就好了.其实并没有太大难度. pbihao用双向链表写过了此题.在本地上我treap狂操他,but在rqnoj上,我依靠反复提交才A掉此题(最后 ...

  7. Luogu1081 NOIP2012 开车旅行 倍增

    题目传送门 为什么NOIP的题目都这么长qwq 话说2012的D1T3和D2T3都是大火题啊qwq 预处理神题 对于这种跳跳跳的题目考虑使用倍增优化枚举.先预处理某个点之后距离最小和次小的城市,然后倍 ...

  8. luogu1081 [NOIp2012]开车旅行 (STL::multiset+倍增)

    先用不管什么方法求出来从每个点出发,A走到哪.B走到哪(我写了一个很沙雕的STL) 然后把每个点拆成两个点,分别表示A从这里出发和B从这里出发,然后连边是要A连到B.B连到A.边长就是这次走的路径长度 ...

  9. 洛谷1081 (NOIp2012) 开车旅行——倍增预处理

    题目:https://www.luogu.org/problemnew/show/P1081 预处理从每个点开始a能走多少.b能走多少.可以像dp一样从后往前推. 但有X的限制.所以该数组可以变成倍增 ...

  10. Luogu 1081 【NOIP2012】开车旅行 (链表,倍增)

    Luogu 1081 [NOIP2012]开车旅行 (链表,倍增) Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已 ...

随机推荐

  1. Flask 学习 十二 用户评论

    评论在数据库中的表示 由于评论和2个模型有关系,分别是谁发了评论,以及评论了哪个文章,所以这次要更新数据库模型 models.py 创建用户评论数据库模型 class Comment(db.Model ...

  2. JUnit单元测试遇到的问题及解决思路

    JUnit是Java单元测试框架,我们在对开发的系统进行单元测试的时候,也遇到了如何测试多个测试用例的问题.  背景:我们的所有测试用例都保存在Excel文件中,该文件包含测试用例和预期输出.我们希望 ...

  3. [USACO4.1]麦香牛块Beef McNuggets

    https://www.luogu.org/problemnew/show/P2737 给出n个数ai,求这n个数不能累加出的最大的数 最大的数无限大或能凑出所有的自然数则输出0 n<=10,a ...

  4. The method getTextContent() is undefined for the type Node

    eclipse 中 如果加入了 其他了xfire 等其他xml解析包的话,使用org.w3c.dom.Node下的getTextContent()方法会出现The method getTextCont ...

  5. nyoj 寻找最大数(二)

    寻找最大数(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 给你一个数字n(可能有前缀0). 要求从高位到低位,进行 进栈出栈 操作,是最后输出的结果最大.   ...

  6. mysql数据库基本操作

    下载地址 http://www.mysql.com/downloads/mysql/ 端口号:3306 用户名:root 密码:自定义 连接到MySQL服务器 >mysql -uroot -pr ...

  7. vue+mint-ui的微博页面(支持评论@添加表情等)

    github地址 https://github.com/KyrieZbw/Sneakers (如果觉得不错就给个小星星) 预览地址 页面展示 技术栈 vue2 + vuex + vue-router ...

  8. CentOS7.4下的 JDK1.8 安装

    一.卸载老的JDK 如果需要卸载OpenJDK,执行以下操作: [root@localhost ~]# rpm -e --nodeps tzdata-java-2014i-1.el7.noarch[r ...

  9. Linux命令基础

    开启Linux操作系统,root用户登录GNOME图形界面,如下图: 切换到虚拟终端2,使用普通用户身份登录,查看系统提示符,如下图: 使用命令退出虚拟终端2上的登录用户,如下图: 切换到虚拟终端5, ...

  10. POJ-2923 Relocation---01背包+状态压缩

    题目链接: https://vjudge.net/problem/POJ-2923 题目大意: 有n个货物,给出每个货物的重量,每次用容量为c1,c2的火车运输,问最少需要运送多少次可以将货物运完 思 ...