记录编号 196831 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2012]开车旅行 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 3.713 s
提交时间 2015-10-22 19:33:23 内存使用 101.79 MiB
显示代码纯文本
#define MAXN 100010UL
#define MAXS 22UL
#define inf (1e14)
#define eps (1e-7)

#define ll long long

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef std::pair<ll,ll> Rtn;

struct Node{
	Node *left,*right;
	ll val,fix;
	Node(){left=right=NULL;return;}
}*root;
ll height[MAXN],x0,n,m,now_pos,pre[2][MAXN][MAXS][3],limit;
inline ll ABS(ll a){return a>0?a:-a;}
inline ll dis(ll i,ll j){
	if(j==-1||i==-1) return (ll)inf;
	return ABS(height[i]-height[j]);
}

inline void Rturn(Node *&a){
	Node *b=a->left;
	a->left=b->right;
	b->right=a;
	a=b;return;
}

inline void Lturn(Node *&a){
	Node *b=a->right;
	a->right=b->left;
	b->left=a;
	a=b;return;
}

inline void Insert(Node *&p,ll val){
	if(!p){
		p=new Node();p->val=val;
		p->fix=rand();return;
	}
	if(height[val]<(height[p->val])){
		Insert(p->left,val);
		if((p->left->fix)<(p->fix)) Rturn(p);
	}
	else{
		Insert(p->right,val);
		if((p->right->fix)<(p->fix)) Lturn(p);
	}
	return;
}

inline ll Find_Smaller(Node *p,ll val){
	if(!p) return -1;
	if(height[p->val]<height[val]){
		int tmp=Find_Smaller(p->right,val);
		if(tmp!=-1) return tmp;
		return p->val;
	}
	return Find_Smaller(p->left,val);
}

inline ll Find_Bigger(Node *p,ll val){
	if(!p) return -1;
	if(height[p->val]>height[val]){
		int tmp=Find_Bigger(p->left,val);
		if(tmp!=-1) return tmp;
		return p->val;
	}
	return Find_Bigger(p->right,val);
}

inline bool comp(ll a,ll b){
	if(a==-1) return false;
	if(b==-1) return true;
	ll d1=dis(now_pos,a),d2=dis(now_pos,b);
	if(d1==d2) return height[a]<height[b];
	return d1<d2;
}

//pre i,j,k,l
/*
i==0 from A
i==1 from B
j 2^k
l==0 where
l==1 A
l==2 B
*/
//f0 f1 now f2 f3

inline Rtn Cal(ll s,ll x){
	Rtn Ans;ll Ans1=0,Ans2=0,last=-1;
	for(;;){
		bool flag=false;
		//printf("%lld->",s);
		for(ll i=limit;i>=0;i--) if((pre[0][s][i][0]!=-1)&&(pre[0][s][i][1]+pre[0][s][i][2]<=x)){
			flag=true;//printf("%lld\n",i);
			Ans1+=pre[0][s][i][1],Ans2+=pre[0][s][i][2],x-=pre[0][s][i][1]+pre[0][s][i][2],s=pre[0][s][i][0];
			last=i;break;
		}
		if(!flag){
			if(last==0&&pre[1][s][0][0]!=-1){
                //printf("_>%lld\n",pre[1][s][0][0]);
				if(x>=pre[1][s][0][1]+pre[1][s][0][2]){
					Ans1+=pre[1][s][0][1],Ans2+=pre[1][s][0][2];
				}
			}
			break;
		}
	}//puts("");
	Ans.first=Ans1,Ans.second=Ans2;
	return Ans;
}

inline void PreWork(){
	for(ll i=n,f[4];i>0;i--){
		memset(f,-1,sizeof(f));
		f[1]=Find_Bigger(root,i);
		if(f[1]!=-1) f[0]=Find_Bigger(root,f[1]);
		f[2]=Find_Smaller(root,i);
		if(f[2]!=-1) f[3]=Find_Smaller(root,f[2]);
		now_pos=i;std::sort(f,f+4,comp);
		pre[0][i][0][0]=f[1];
		pre[0][i][0][1]=dis(i,f[1]);
		pre[0][i][0][2]=0;
		pre[1][i][0][0]=f[0];
		pre[1][i][0][1]=0;
		pre[1][i][0][2]=dis(i,f[0]);
	// 	if(i==3) printf("%lld %lld\n",pre[0][i][0][0],pre[1][i][0][0]);
		Insert(root,i);
	}
	scanf("%lld%lld",&x0,&m);
	for(int j=1,arr;(1<<j)<=n;j++){
		limit=j;
		for(int i=1;i<=n;i++){
			//updating pre[mask][i][j][l]
			if(j==1){
				if(pre[0][i][j-1][0]==-1){
					pre[0][i][j][0]=-1;
					pre[0][i][j][1]=pre[0][i][j][2]=inf;
				}
				else{
					arr=pre[0][i][j-1][0];
					pre[0][i][j][0]=pre[1][arr][j-1][0];
					pre[0][i][j][1]=pre[0][i][j-1][1]+pre[1][arr][j-1][1];
					pre[0][i][j][2]=pre[0][i][j-1][2]+pre[1][arr][j-1][2];
				}
			}
			else{
				if(pre[0][i][j-1][0]==-1){
					pre[0][i][j][0]=-1;
					pre[0][i][j][1]=pre[0][i][j][2]=inf;
				}
				else{
					arr=pre[0][i][j-1][0];
					pre[0][i][j][0]=pre[0][arr][j-1][0];
					pre[0][i][j][1]=pre[0][i][j-1][1]+pre[0][arr][j-1][1];
					pre[0][i][j][2]=pre[0][i][j-1][2]+pre[0][arr][j-1][2];
				}
			}
		}
	}
	ll best_=1;double comp_Ans=inf;
	for(ll i=1;i<=n;i++){
		Rtn Ans=Cal(i,x0);
		double temp_rs=(Ans.second==0)?((double)(inf)):((double)((double)Ans.first/(double)Ans.second));
		if(comp_Ans>temp_rs) comp_Ans=temp_rs,best_=i;
	}
	printf("%lld\n",best_);
	return;
}

inline void Work(){
	ll s,x;
	scanf("%lld%lld",&s,&x);
	Rtn Ans=Cal(s,x);printf("%lld %lld",Ans.first,Ans.second);
	return;
}

int main(){
	freopen("drive.in","r",stdin);freopen("drive.out","w",stdout);
	scanf("%lld",&n);memset(pre,-1,sizeof(pre));
	for(ll i=1;i<=n;i++) scanf("%lld",&height[i]);
	PreWork();for(ll i=1;i<=m;i++,puts("")) Work();
	return 0;
}