记录编号 443536 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2012]开车旅行 最终得分 100
用户昵称 Gravatar__stdcall 是否通过 通过
代码语言 C++ 运行时间 1.286 s
提交时间 2017-08-31 10:39:46 内存使用 43.42 MiB
显示代码纯文本
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <set>
#include <utility>

using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef set<pii>::iterator siter;
const int MAXN = 100010;
const int LOGN = 20;
const int MAXM = 100010;
int nowarn;

int n, h[MAXN], x0;
int m, si[MAXM], xi[MAXM];

void input() {
	nowarn = scanf( "%d", &n );
	for( int i = 1; i <= n; ++i )
		nowarn = scanf( "%d", h+i );
	nowarn = scanf( "%d", &x0 );
	nowarn = scanf( "%d", &m );
	for( int i = 0; i < m; ++i )
		nowarn = scanf( "%d%d", si+i, xi+i );
}

struct Info {
	int to;
	ll adis, bdis;
	Info():
		to(0), adis(0), bdis(0) {}
	Info( int to, ll adis, ll bdis ):
		to(to), adis(adis), bdis(bdis) {}
};

Info goa[MAXN], gob[MAXN], go[MAXN][LOGN];

set<pii> s;
bool better( pii a, pii b ) {
	if( a.first == b.first )
		return h[a.second] < h[b.second];
	return a.first < b.first;
}
pii find1( pii tmp[], int size ) {
	pii ans = tmp[0];
	for( int i = 1; i < size; ++i )
		if( better( tmp[i], ans ) )
			ans = tmp[i];
	return ans;
}
pii find2( pii tmp[], int size ) {
	pii ans1 = tmp[0], ans2 = tmp[1];
	if( better( ans2, ans1 ) )
		swap( ans1, ans2 );
	for( int i = 2; i < size; ++i )
		if( better( tmp[i], ans1 ) )
			ans2 = ans1, ans1 = tmp[i];
		else if( better( tmp[i], ans2 ) )
			ans2 = tmp[i];
	return ans2;
}
void prelude() {
	for( int i = n; i >= 1; --i ) {
		if( i <= n-1 ) {
			pii tmp[2];
			int size = 0;
			siter it = s.lower_bound( pii( h[i], i ) );
			if( it != s.end() )
				tmp[size++] = pii( abs( h[i] - it->first ), it->second );
			if( it != s.begin() ) {
				--it;
				tmp[size++] = pii( abs( h[i] - it->first ), it->second );
			}
			tmp[0] = find1( tmp, size );
			gob[i].to = tmp[0].second;
			gob[i].bdis = tmp[0].first;
		}
		if( i <= n-2 ) {
			pii tmp[4];
			int size = 0;
			siter it = s.lower_bound( pii( h[i], i ) );
			if( it != s.end() ) {
				tmp[size++] = pii( abs( h[i] - it->first ), it->second );
				++it;
				if( it != s.end() )
					tmp[size++] = pii( abs( h[i] - it->first ), it->second );
				--it;
			}
			if( it != s.begin() ) {
				--it;
				tmp[size++] = pii( abs( h[i] - it->first ), it->second );
				if( it != s.begin() ) {
					--it;
					tmp[size++] = pii( abs( h[i] - it->first ), it->second );
				}
			}
			tmp[0] = find2( tmp, size );
			goa[i].to = tmp[0].second;
			goa[i].adis = tmp[0].first;
		}
		s.insert( pii( h[i], i ) );
	}
	for( int i = 1; i <= n; ++i ) {
		int mid = goa[i].to;
		go[i][0].adis = goa[i].adis;
		go[i][0].bdis = gob[mid].bdis;
		go[i][0].to = gob[mid].to;
	}
	bool flag = true;
	for( int k = 0; flag; ++k ) {
		flag = false;
		for( int i = 1; i <= n; ++i ) {
			int mid = go[i][k].to;
			if( !mid ) continue;
			flag = true;
			go[i][k+1].to = go[mid][k].to;
			go[i][k+1].adis = go[i][k].adis + go[mid][k].adis;
			go[i][k+1].bdis = go[i][k].bdis + go[mid][k].bdis;
		}
	}
}

pii simulate( int s, int x ) {
	int adis = 0, bdis = 0;
	for( int k = LOGN-1; k >= 0; --k ) {
		if( !go[s][k].to ) continue;
		ll dis = go[s][k].adis + go[s][k].bdis;
		if( dis > x ) continue;
		x -= (int)dis;
		adis += (int)go[s][k].adis;
		bdis += (int)go[s][k].bdis;
		s = go[s][k].to;
	}
	if( goa[s].to && goa[s].adis <= x )
		adis += (int)goa[s].adis;
	return pii(adis, bdis);
}
void solve1() {
	double minv = 1e100;
	int from = int(max_element( h+1, h+n+1 ) - h);
	for( int i = 1; i <= n; ++i ) {
		pii tmp = simulate(i, x0);
		if( !tmp.second ) continue;
		double div = (double)tmp.first / tmp.second;
		if( div < minv )
			minv = div, from = i;
	}
	printf( "%d\n", from );
}
void solve2() {
	for( int i = 0; i < m; ++i ) {
		pii tmp = simulate( si[i], xi[i] );
		printf( "%d %d\n", tmp.first, tmp.second );
	}
}

int main() {
	freopen( "drive.in", "r", stdin );
	freopen( "drive.out", "w", stdout );
	input(), prelude(), solve1(), solve2();
	return 0;
}