ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[vijos1780][NOIP2012]开车旅行

2021-11-24 21:33:38  阅读:161  来源: 互联网

标签:vijos1780 旅行 路程 NOIP2012 10 int 城市 行驶 g2


Description

小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行驶的路程总数。

HINT

\(1≤N≤10^5,1≤M≤10^4,-10^9≤H_i≤10^9,0≤X_0≤10^9,1≤S_i≤N,0≤X_i≤10^9\),保证\(H_i\)互不相同.

Solution

预处理出从每个城市出发距离第一小和第二小的城市.
\(f[i][j]\)表示从\(i\)出发,走\(2^j\)轮到达的城市.
\(g1[i][j]\)表示从\(i\)出发,走\(2^j\)轮小A走的路程.
\(g2[i][j]\)表示从\(i\)出发,走\(2^j\)轮小B走的路程.
倍增求解即可.

#define K 18
#define N 100005
#define INF 1000000005
typedef long long ll;
struct city{
	int h,x;
}h[N];
int f[N][K],g1[N][K],g2[N][K],nxt1[N],nxt2[N],n,m;
set<city> s;
set<city>::iterator xx;
bool operator < (city x,city y){
	if(x.h!=y.h) return x.h<y.h;
	return x.x<y.x;
}
//x比y优 
inline bool cmp(int u,int x,int y){
	if(!x) return false;
	if(!y) return true;
	if(abs(h[x].h-h[u].h)!=abs(h[y].h-h[u].h))
		return abs(h[x].h-h[u].h)<abs(h[y].h-h[u].h);
	return h[x].h<h[y].h;
}
inline int dis(int x,int y){
	if(x&&y) 
		return abs(h[x].h-h[y].h)<INF?abs(h[x].h-h[y].h):INF;
	return INF;
}
inline void drive(int u,int x,int &d1,int &d2){
	int i;d1=d2=0;
	while(x){
		for(i=K-1;i>=0&&g1[u][i]+g2[u][i]>x;--i);
		if(i<0) return;
		x-=(g1[u][i]+g2[u][i]);
		d1+=g1[u][i];d2+=g2[u][i];
		u=f[u][i];
	}
}
inline bool cmp2(int j,int k,int d1,int d2,int i,int id){
	if(d1<0) return true;
	if(d2&&k) return 1ll*j*d2<1ll*d1*k||(1ll*j*d2==1ll*d1*k&&h[i].h>h[id].h);
	if(d2||k) return k;
	return h[i].h>h[id].h;
}
inline void Aireen(){
	n=read();
	for(int i=1;i<=n;++i)
		h[i].h=-read(),h[i].x=i;
	city c1,c2;
	s.clear();
	for(int i=n-1;i;--i){
		s.insert(h[i+1]);
		c1=(*s.upper_bound(h[i]));
		if(s.count(c1)){
			s.erase(c1);
			c2=(*s.upper_bound(h[i]));
			s.insert(c1);
			nxt1[i]=c1.x;nxt2[i]=c2.x;
		}
		else continue;
	}
	
	s.clear();
	for(int i=1;i<=n;++i)
		h[i].h=-h[i].h;
	for(int i=n-1;i;--i){
		s.insert(h[i+1]);
		c1=(*s.upper_bound(h[i]));
		
		if(s.count(c1)){
			s.erase(c1);
			c2=(*s.upper_bound(h[i]));
			s.insert(c1);
			if(cmp(i,c1.x,nxt1[i])){
				nxt2[i]=nxt1[i];
				nxt1[i]=c1.x;
				if(s.count(c2)&&cmp(i,c2.x,nxt2[i]))
					nxt2[i]=c2.x; 
			}
			else if(cmp(i,c1.x,nxt2[i]))
				nxt2[i]=c1.x; 
		}
		else continue;
	}
	 
	for(int j=0;j<K;++j)
		g1[n][j]=g2[n][j]=g1[0][j]=g2[0][j]=INF; 
	for(int i=n-1;i;--i){
		f[i][0]=nxt2[i];
		f[i][1]=nxt1[nxt2[i]];
		g1[i][0]=g1[i][1]=dis(i,nxt2[i]);
		g2[i][1]=dis(nxt2[i],nxt1[nxt2[i]]);
		for(int j=2;j<K;++j){
			f[i][j]=f[f[i][j-1]][j-1];
			g1[i][j]=g1[i][j-1]+g1[f[i][j-1]][j-1];
			if(g1[i][j]>INF) g1[i][j]=INF;
			g2[i][j]=g2[i][j-1]+g2[f[i][j-1]][j-1];
			if(g2[i][j]>INF) g2[i][j]=INF;
		}
	}
	
	int u,x,d1=-1,d2,id;
	x=read();
	for(int i=1,j,k;i<=n;++i){
		drive(i,x,j,k);
		if(cmp2(j,k,d1,d2,i,id)) d1=j,d2=k,id=i;
	}
	printf("%d\n",id);
	
	m=read();
	while(m--){
		u=read();x=read();
		drive(u,x,d1,d2);
		printf("%d %d\n",d1,d2);
	}
}

2017-10-27 13:30:24

标签:vijos1780,旅行,路程,NOIP2012,10,int,城市,行驶,g2
来源: https://www.cnblogs.com/AireenYe/p/15600163.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有