제출 #118344

#제출 시각아이디문제언어결과실행 시간메모리
118344BruteforcemanTreasure Hunt (CEOI11_tre)C++11
10 / 100
1827 ms62840 KiB
#include "bits/stdc++.h"
using namespace std;

int current_point;
int node;

int link[400010];
int id[400010];
int len[400010];

map <int, int> mp;
set <int> s;
int anc[20][400010];

int dep[400010], dist[400010];

const int logn = 19;

void init()
{
	s.clear();
	mp.clear();
	node = 1;
	current_point = 1;
	
	id[1] = 1;
	len[1] = 0;
	link[1] = -1;
	mp[1] = node;
	s.insert(1);
}

void path(int a, int sq)
{
	current_point += sq;
	id[++node] = current_point;
	len[node] = sq;
	link[node] = a;
	mp[current_point] = node;
	s.insert(current_point);

	int par = mp[*s.lower_bound(a)];
	anc[0][node] = par;

	dep[node] = dep[par] + 1;
	dist[node] = dist[par] + len[par] - (id[par] - a);

	for(int i = 1; i <= logn; i++) {
		anc[i][node] = anc[i - 1][anc[i - 1][node]];
	}
}

int find_node(int x) {
	return mp[*s.lower_bound(x)];
}

int lca(int p, int q) {
	if(dep[p] > dep[q]) swap(p, q);
	for(int i = logn; i >= 0; i--) {
		if(dep[q] - (1 << i) >= dep[p]) {
			q = anc[i][q];
		}
	}
	if(p == q) return p;
	for(int i = logn; i >= 0; i--) {
		if(anc[i][p] != anc[i][q]) {
			p = anc[i][p];
			q = anc[i][q];
		}
	}
	return anc[0][p];
}

int lift(int p, int deep) {
	for(int i = logn; i >= 0; i--) {
		if(dep[p] - (1 << i) >= deep) {
			p = anc[i][p];
		}
	}
	return p;
}


int distance(int p, int q) {
	int s = find_node(p);
	int t = find_node(q);
	int pr = lca(s, t);

	int lp, lq;
	long long ans = dist[s] + dist[t] - 2 * dist[pr];

	ans += len[s] - abs(id[s] - p);
	ans += len[t] - abs(id[t] - q);

	lp = (s == pr) ? p : link[lift(s, dep[pr] + 1)];
	lq = (t == pr) ? q : link[lift(t, dep[pr] + 1)];

	ans -= len[pr] - abs(id[pr] - min(lp, lq));
	ans -= len[pr] - abs(id[pr] - min(lp, lq));
	return ans;
}

int move_up(int x, int up) {
	int s = find_node(x);
	int nxt_dist = len[s] - abs(id[s] - x);
	if(nxt_dist > up) {
		return x - up;
	}
	up -= nxt_dist;
	for(int i = logn; i >= 0; i--) {
		if(dep[s] < (1 << i)) continue;
		int p = anc[i][s];
		if(dist[s] - dist[p] < up) {
			up -= dist[s] - dist[p];
			s = p;
		}
	}
	s = link[s];
	return s - up;
}

int dig(int p, int q)
{
	int s = find_node(p);
	int t = find_node(q);
	int pr = lca(s, t);
	int lp, lq;
	lp = (s == pr) ? p : link[lift(s, dep[pr] + 1)];
	lq = (t == pr) ? q : link[lift(t, dep[pr] + 1)];

	int tot = distance(p, q);
	int med = tot / 2;
	if(med <= distance(p, lp)) {
		return move_up(p, med);
	}
	med -= distance(p, lp);
	if(med <= abs(lp - lq)) {
		if(lp < lq) return lp + med;
		else return lp - med;
	}
	med -= abs(lp - lq);
	return move_up(q, distance(q, lq) - med);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...