描述

小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为\(H_i\),城市\(i\)和城市\(j\)之间的距离\(d(i,j)\)恰好是这两个城市海拔高度之差的绝对值,即\(d(i,j) = |H_i - H_j|\)。

旅行过程中,小$A$和小$B$轮流开车,第一天小$A$开车,之后每天轮换一次。他们计划选择一个城市$S$作为起点,一直向东行驶,并且最多行驶$X$公里就结束旅行。小$A$和小$B$的驾驶风格不同,小$B$总是沿着前进方向选择一个最近的城市作为目的地,而小$A$总是沿着前进方向选择第二近的城市作为目的地(注意:本题中如果当前城市到两个城市的距离相同,则认为离海拔低的那个城市更近)。如果其中任何一人无法按照自己的原则选择目的城市,或者到达目的地会使行驶的总距离超出$X$公里,他们就会结束旅行。 
在启程之前,小$A$想知道两个问题: 
1.对于一个给定的$X=X_0$,从哪一个城市出发,小$A$开车行驶的路程总数与小$B$行驶的路程总数的比值最小(如果小$B$的行驶路程为$0$,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小$A$开车行驶的路程总数与小$B$行驶的路程总数的比值都最小,则输出海拔最高的那个城市。 
2. 对任意给定的$X=X_i$和出发城市$S_i$,小$A$开车行驶的路程总数以及小$B$行驶的路程总数。

输入格式

第一行包含一个整数$N$,表示城市的数目。 
第二行有$N$个整数,每两个整数之间用一个空格隔开,依次表示城市$1$到城市$N$的海拔高度,即$H_1,H_2,……,H_n,$且每个$H_i$都是不同的。 
第三行包含一个整数$X_0$。 
第四行为一个整数$M$,表示给定$M$组$S_i$和$X_i$。 
接下来的$M$行,每行包含$2$个整数$S_i$和$X_i$,表示从城市$S_i$出发,最多行驶$X_i$公里。

输出格式

输出共$M+1$行。 
第一行包含一个整数$S_0$,表示对于给定的$X_0$,从编号为$S_0$的城市出发,小$A$开车行驶的路程总数与小$B$行驶的路程总数的比值最小。 
接下来的$M$行,每行包含$2$个整数,之间用一个空格隔开,依次表示在给定的$S_i$和$X_i$下小$A$行驶的里程总数和小$B$行驶的里程总数。

提示

对于$30\%$的数据,有$1\leq N\leq 20,1\leq M\leq 20$; 
对于$40\%$的数据,有$1\leq N\leq 100,1\leq M\leq 100$; 
对于$50\%$的数据,有$1\leq N\leq 100,1\leq M\leq 1000$;
对于$70\%$的数据,有$1\leq N\leq 1000,1\leq M\leq 10000$;
对于$100\%$的数据,有$1\leq N\leq 10^5,1\leq M\leq 10^4,-10^9\leq H\leq 10^9,0\leq X_0\leq 10^9,1\leq S_i\leq N,0\leq Xi\leq 10^9$,数据保证$H_i$互不相同。

  这道题是很久以前刷$noip$题的时候留下来未解决的,现在来填个坑……

  一开始我写的是平衡树,现在看了$NOI$年鉴之后才意识到可以使用排序加链表来解决……

  我们先考虑如果我们知道了每个位置往后最近的城市和次近的城市,那么我们可以使用倍增来解决这道题。我们处理出每个位置往后跳$2^i$所在的位置以及此时小$A$走过的距离和小$B$走过的距离,第二问的每个询问就可以在$O(\log n)$的复杂度内得到解决。而第一位又可以枚举起点算一算,所以,我们主要是要找出每个点往后会走到哪儿。

  当然,我们可以考虑从后往前扫一遍,那么我们需要支持的操作有两个:加入一个值,以及查询比某个值大的最小、次小值,比这个值小的最大、次大值。这样的话我们就需要一颗平衡树。虽然直接调用$set$即可解决,但是常数非常之大,我之前就在$vijos$上被卡$TLE$了一个点,并且死活过不去。

  我们现在来考虑一种新的方法。其实这种方法在今年$noip$的初赛中就已经出现了。我们可以把所有的高度排好序,并且记录下原位置。然后,我们按照排序之后的顺序构建一个双向链表,按原顺序扫一遍。在这个双向链表中我们可以非常轻易地找出我们所需要的信息,并且每次用完这个点之后我们需要将它删除,在这个双向链表中也可以在常数复杂度内做到。所以,我们就没有必要使用平衡树了。

  下面贴代码(代码有点丑):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010
#define INF (1LL<<60) using namespace std;
typedef long long llg; struct data{
llg x;int y;
data(llg a=0,int b=0):x(a),y(b){}
}a[5];
int wh[maxn],n,m,pr[maxn],ne[maxn],ns;
int X,to[maxn][17],na[maxn],nb[maxn],fa[maxn],fb[maxn];
llg ca,cb,va[maxn][17],vb[maxn][17],h[maxn];
double now; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} bool operator < (data x,data y){
if(x.x!=y.x) return x.x<y.x;
return h[x.y]<h[y.y];
} void qsort(int l,int r){
int i=l,j=r,mid=h[wh[(l+r)>>1]];
while(i<=j){
while(h[wh[i]]<mid) i++;
while(h[wh[j]]>mid) j--;
if(i<=j) swap(wh[i++],wh[j--]);
}
if(i<r) qsort(i,r);
if(j>l) qsort(l,j);
} void pre(){
wh[n+1]=ne[n+1]=n+1; h[0]=-INF; h[n+1]=INF;
for(int i=1;i<=n;i++) ne[wh[i]]=wh[i+1],pr[wh[i]]=wh[i-1];
for(int i=1;i<=n;i++){
a[1]=data(h[ne[i]]-h[i],ne[i]); a[2]=data(h[ne[ne[i]]]-h[i],ne[ne[i]]);
a[3]=data(h[i]-h[pr[i]],pr[i]); a[4]=data(h[i]-h[pr[pr[i]]],pr[pr[i]]);
if(pr[i]>=1) ne[pr[i]]=ne[i]; if(ne[i]<=n) pr[ne[i]]=pr[i];
sort(a+1,a+5); nb[i]=a[1].y%(n+1); na[i]=a[2].y%(n+1);
fa[i]=a[2].x; fb[i]=a[1].x;
}
for(int i=1;i<=n;i++){
if(na[i]) va[i][0]=fa[i],to[i][0]=na[i];
if(nb[na[i]]) va[i][1]=va[i][0],vb[i][1]=fb[na[i]],to[i][1]=nb[na[i]];
}
for(int j=2;j<=16;j++){
for(int i=1;i<=n;i++){
if(to[to[i][j-1]][j-1]){
va[i][j]=va[i][j-1]+va[to[i][j-1]][j-1];
vb[i][j]=vb[i][j-1]+vb[to[i][j-1]][j-1];
to[i][j]=to[to[i][j-1]][j-1];
}
}
}
} double cal(){
if(!cb) return (1LL<<60);
return (double)ca/(double)cb;
} void solve(int S,int X){
ca=cb=0;
for(int i=16;i>=0;i--)
if(to[S][i] && ca+cb+va[S][i]+vb[S][i]<=X)
ca+=va[S][i],cb+=vb[S][i],S=to[S][i];
} int main(){
File("a");
n=getint();
for(int i=1;i<=n;i++) h[i]=getint(),wh[i]=i;
qsort(1,n); pre(); now=1e100; X=getint();
for(int i=1;i<=n;i++){
solve(wh[i],X); double x=cal();
if(x<=now) now=x,ns=wh[i];
}
printf("%d\n",ns);
m=getint();
while(m--){
int s=getint(),x=getint(); solve(s,x);
printf("%lld %lld\n",ca,cb);
}
return 0;
}

  几个提交的地方:vijos P1780codevs 1199

vijos P1780 【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的限制.所以该数组可以变成倍增 ...

随机推荐

  1. ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  2. 钉钉js依赖库学习

    看别人用的依赖库的好处在于,你知道有什么可以用,什么可以借鉴.(钉钉——协作桌面应用) PS:人最怕是不知道,而不是你不会. 1. jQuery 钉钉使用了1.9.1版本的jQuery,jQuery作 ...

  3. jquery中 $(document).ready()和window.onload的区别

    1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 ...

  4. js 阻止事件冒泡和默认行为 preventDefault、stopPropagation、return false

    preventDefault: preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为.既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就 ...

  5. JAVA简单工厂模式(从现实生活角度理解代码原理)

    简单工厂模式(Simple Factory),说他简单是因为我们可以将此模式比作一个简单的民间作坊,他们只有固定的生产线生产固定的产品.也可以称他为静态工厂设计模式,类似于之前提到过静态代理设计模式, ...

  6. CoreData

    之前在学习使用SQLite时, 需要编写大量的sql语句,完成数据的增删改查,但对于不熟悉sql语句的开发人员来说,难度较大,调试程序比较困难. 由此出现CoreData框架,将sql的操作转换成为对 ...

  7. JavaScript的个人学习随手记(二)

    JS HTML DOM 改变 HTML 输出流 JavaScript 能够创建动态的 HTML 内容: 今天的日期是: Sat Sep 24 2016 15:06:50 GMT+0800 (中国标准时 ...

  8. ASP.NET获取真正的客户端IP地址的6种方法

    Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的IP地址,而不是真 ...

  9. EntityFramework 数据库连接可用代码动态设定

    摘自:http://blog.csdn.net/dyllove98/article/details/9289553 数据库生成位置可控制(其实主要就是DbContext的构造函数) 1.使用DbCon ...

  10. Asp.Net MVC+BootStrap+EF6.0实现简单的用户角色权限管理10

    今天把用户的菜单显示和页面的按钮显示都做好了,下面先来个效果图 接下来说下我实现的方法: 首先我在每个方法前面都加了这个属性, /// <summary> /// 表示当前Action请求 ...