记录编号 298363 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2012]开车旅行 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 1.926 s
提交时间 2016-08-20 20:45:24 内存使用 108.65 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
using namespace std;
const int N=200010,maxl=1000000000;
int n,m,h[N],A[N],level,s0,x0;
//a[i]表示到了i地,由B开车的目的地;a[i+n]表示到了i地,由A开车的目的地 
set<int> S;
map<int,int> M;
bool cmp(const int x,const int y){
	return abs(x-level)==abs(y-level)?x<y:abs(x-level)<abs(y-level);
}
int P(int x){return x>n?x-n:x;}
struct element{int f;long long a,b,l;}dp[N][20];
long long ansa,ansb;
void ask(int s0,int x0){
	long long ans=0;int i=19;
	ansa=ansb=0;
	while (1){
		while (i>=0&&dp[s0][i].l>x0) i--;
		if (i<0) break;
		ans+=dp[s0][i].l;
		ansa+=dp[s0][i].a;
		ansb+=dp[s0][i].b;
		x0-=dp[s0][i].l;
		s0=dp[s0][i].f;
	}
}
int main()
{
	freopen("drive.in","r",stdin);
	freopen("drive.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&h[i]),M[h[i]]=i;
	h[0]=-maxl;
	for (int i=n;i;i--){
		S.insert(level=h[i]);
		int q[4]={0},cnt=0;
		set<int>::iterator l=S.find(h[i]),r=l;
		for (int j=1;j<=2;j++){
			if (l==S.begin()) break;
			l--;q[++cnt]=*l;
		}
		for (int j=1;j<=2;j++){
			r++;
			if (r==S.end()) break;
			q[++cnt]=*r;
		}
		sort(q+1,q+cnt+1,cmp);
		if (cnt>=1) A[i]=M[q[1]]+n;
		if (cnt>=2) A[i+n]=M[q[2]];
	}
	for (int i=1;i<=n*2;i++){
		dp[i][0].f=A[i];
		if (i<=n) dp[i][0].b=abs(h[i]-h[P(A[i])]);
			else dp[i][0].a=abs(h[i-n]-h[A[i]]);
		dp[i][0].l=dp[i][0].a+dp[i][0].b;
	}
	for (int j=1;j<20;j++)
	for (int i=0;i<=n*2;i++){
		int fa=dp[i][j-1].f;
		dp[i][j].f=dp[fa][j-1].f;
		dp[i][j].l=dp[i][j-1].l+dp[fa][j-1].l;
		dp[i][j].a=dp[i][j-1].a+dp[fa][j-1].a;
		dp[i][j].b=dp[i][j-1].b+dp[fa][j-1].b;
	}
	
	//第一问 
	int ans=0;
	double Min=maxl;
	scanf("%d",&x0);
	for (s0=1;s0<=n;s0++){
		ask(s0+n,x0);
		if (Min==maxl){
			if (h[s0]>h[ans]||ansb==0) ans=s0;
			if (ansb!=0) ans=s0,Min=double(ansa)/ansb;
		}
		else{
			if (ansb!=0&&double(ansa)/ansb<Min)
				Min=double(ansa)/ansb,ans=s0;
		}
	}
	printf("%d\n",ans);
	
	//第二问 
	scanf("%d",&m);
	while (m--){
		scanf("%d%d",&s0,&x0);
		ask(s0+n,x0);
		printf("%lld %lld\n",ansa,ansb);
	}
	return 0;
}