vijos P1780 【NOIP2012】 开车旅行
描述
小\(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 P1780,codevs 1199
vijos P1780 【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的限制.所以该数组可以变成倍增 ...
随机推荐
- JavaScript中this指针指向的彻底理解
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 这一点与函数中自由变量Action-varibal不同 var ...
- 使用gulp+browser-sync搭建前端项目自动化以及自动刷新
前段时间使用了gulp+browser-sync才发现这个东西真的很好用. 准备工作:(1).安装nodejs.gulp是基于nodejs使用的,所以先安装nodejs,https://nodejs. ...
- ArcSDE10.2.2使用SQL操作ST_Geometry时报ORA-28579
给esri中国的客服打电话被告知,是一直存在这个bug,arcgis10.2对应的oracle数据库版本要用11.2.0.3及以上的: 1.数据库升级可以用打补丁的当方式. 2.直接重装,我这里是直接 ...
- [转]IPython Notebook简介1
原文:http://hyry.dip.jp/tech/slice/slice.html/35 Python Notebook简介1 作者 : RY 标签: cython ipython-note ...
- AD RMS 配置指南 附结合SharePoint使用
本文的 RMS配置 是独立安装的配置手册,如果要和SharePoint结合使用可以作为参考指南. SharePoint安装可参考 点击链接 同样可提供给Office使用,当然Exchange也可以使用 ...
- Objective-C Runtime 运行时之四:Method Swizzling
理解Method Swizzling是学习runtime机制的一个很好的机会.在此不多做整理,仅翻译由Mattt Thompson发表于nshipster的Method Swizzling一文. Me ...
- 深入剖析通知中心和KVO
深入剖析通知中心和KVO 要先了解KVO和通知中心,就得先说说观察者模式,那么观察者模式到底是什么呢?下面来详细介绍什么是观察者模式. 观察者模式 -A对B的变化感兴趣,就注册成为B的观察者,当B发生 ...
- js(javascript)与OC(Objective-C)交互
实质上oc与js的通信交互就是发送消息,也即函数调用,iOS7以后官方公布JavaScriptCore framework中很方便我们对他们之间的相互调用.在以前我们只能通过UIWebView的UIW ...
- 解决方法:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
在Windows Server 2008 x64 上部署一个Vs 2008开发的.net2.0 的asp.net web 程序,调用了office的组件来导入导出excel文件,其中托管管道模式为集成 ...
- [转]看懂UML类图
这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图所表达的含义和最终的代码 ...