记录编号 199167 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2012]开车旅行 最终得分 100
用户昵称 Gravatarthomount 是否通过 通过
代码语言 C++ 运行时间 2.411 s
提交时间 2015-10-25 23:31:39 内存使用 52.17 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int read() {
	char ch = getchar();
	while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
	int ans = 0, flag = 1;
	if (ch == '-') flag = -1, ch = getchar();
	while (ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
	return ans * flag;
}
const int N = 100010;
int h[N];
struct point {
	int x, t, w, size;
	point * ls, * rs;
	point(int x = 0, int t = 0, int w = 0): t(t), w(w), x(x), ls(0), rs(0), size(1) {}
	void update() {
		size = 1;
		if (ls) size += ls->size;
		if (rs) size += rs->size;
	}
} d[5*N];
int tot = 0;
typedef point * link;
link head;
int aa = 1, bb = 2, cc = 509, mm = 1000000007;
link make(int x, int t) {
	d[++tot] = point(x, t, aa);
	aa = (aa * bb + cc) % mm;
	return &d[tot];
}
struct inf {
	int f, x, t;
	inf(int x = 0, int t = 0, int f = 0): x(x), t(t), f(f) {}
} q[10];
bool operator < (inf a, inf b) {return (a.x == b.x)? (a.f < b.f):(a.x < b.x);}

void split(link p, int x, link & p1, link & p2) {
	if (!p) {p1 = p2 = 0; return;}
	if (x <= p->x) {
		split(p->ls, x, p1, p->ls);
		p2 = p;
	} else {
		split(p->rs, x, p->rs, p2);
		p1 = p;
	}
	p->update();
}
link merge(link p1, link p2) {
	if (!p1) return p2; if (!p2) return p1;
	if (p1->w < p2->w) {
		p1->rs = merge(p1->rs, p2);
		p1->update();
		return p1;
	} else {
		p2->ls = merge(p1, p2->ls);
		p2->update();
		return p2;
	}
}
link getmax(link p) {
	if (!p) return 0;
	while (p->rs) p = p->rs;
	return p;
}
link getmin(link p) {
	if (!p) return 0;
	while (p->ls) p = p->ls;
	return p;
}

struct move {
	int d;
	long long x, y;
	move(int d = 0, long long x = 0, long long y = 0): d(d), x(x), y(y) {}
} a[N][20], b[N];
move operator + (move a, move b) {
	return move(b.d, a.x + b.x, a.y + b.y);
}
bool judge(long long a, long long b, long long c, long long d) {
	if (!d) return false;
	if (!b) return true; 
	return ((double)a / b > (double)c / d);
}
int main() {
	freopen("drive.in", "r", stdin);
	freopen("drive.out", "w", stdout);
	int n = read();
	for (int i = 1; i <= n; i++) h[i] = read();
	
	head = 0;
	for (int i = n; i; i--) {
		link p1, p2;
		split(head, h[i], p1, p2);
		int r = 0;
		if (p1) {
			link p11 = getmax(p1);
			q[++r] = inf(h[i]-p11->x, p11->t, 0);
			if (p1->size > 1) {
				link p3, p4;
				split(p1, p11->x, p3, p4);
				link p5 = getmax(p3);
				q[++r] = inf(h[i]-p5->x, p5->t, 0);
				p1 = merge(p3, p4);
			}
		}
		if (p2) {
			link p11 = getmin(p2);
			q[++r] = inf(p11->x-h[i], p11->t, 1);
			if (p2->size > 1) {
				link p3, p4;
				split(p2, p11->x+1, p3, p4);
				link p5 = getmin(p4);
				q[++r] = inf(p5->x-h[i], p5->t, 1);
				p2 = merge(p3, p4);
			}
		}
		
		sort(q+1, q+r+1);
		if (r >= 1) b[i] = move(q[1].t, 0, abs(h[q[1].t]-h[i]));
		if (r >= 2) a[i][0] = move(q[2].t, abs(h[q[2].t] - h[i]), 0);
		head = merge(p1, merge(make(h[i], i), p2));
		
	}
	
//	for (int i = 1; i <= n; i++) printf("%d %d\n", a[0][i][0], a[1][i][0]);
	
	for (int i = 1; i <= n; i++) if (a[i][0].d && b[a[i][0].d].d) a[i][1] = a[i][0] + b[a[i][0].d];
	int T = 0;
	for (int i = 2; (1 << i) <= n; i++) {
		for (int j = 1; j <= n; j++) if (a[j][i-1].d && a[a[j][i-1].d][i-1].d) a[j][i] = a[j][i-1] + a[a[j][i-1].d][i-1];
		T = i;
	}
	
	int X0 = read(), w;
	long long ansA = 1, ansB = 0;
	for (int i = 1; i <= n; i++) {
		long long s = 0;
		long long A = 0, B = 0;
		int st = i;
		for (int j = T; j >= 0; j--) {
			if (a[st][j].d && a[st][j].x + a[st][j].y + s <= X0) {
				s += a[st][j].x + a[st][j].y;
				A += a[st][j].x; B += a[st][j].y;
				st = a[st][j].d;
			}
		}
		if (judge(ansA, ansB, A, B)) ansA = A, ansB = B, w = i;
	}
	
	printf("%d\n", w);
	
	int m = read();
	for (int i = 1; i <= m; i++) {
		int st = read(), x = read();
		long long s = 0, A = 0, B = 0;
		for (int j = T; j >= 0; j--) {
			if (a[st][j].d && a[st][j].x + a[st][j].y + s <= x) {
				s += a[st][j].x + a[st][j].y;
				A += a[st][j].x; B += a[st][j].y;
				st = a[st][j].d;
			}
		}
		printf("%lld %lld\n", A, B);
	}
	
	return 0;
}