Submission #383721

#TimeUsernameProblemLanguageResultExecution timeMemory
383721rqiDesignated Cities (JOI19_designated_cities)C++14
56 / 100
2003 ms53472 KiB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

typedef vector<int> vi;

#define f first
#define s second
#define mp make_pair
#define pb push_back

#define sz(x) (int)(x).size()

void ckmax(ll&a, ll b){
	a = max(a, b);
}

const int mx = 200005;
int N;
int A[mx];
int B[mx];
ll C[mx];
ll D[mx];
int E[mx];

vector<pair<int, ll>> adj[mx];
ll tot_cost;
ll ans[mx];

bool done[mx];

int sub[mx];
vi cen_nodes;

void genSub(int node, int p = -1){
	cen_nodes.pb(node);
	sub[node] = 1;
	for(auto u: adj[node]){
		if(u.f == p || done[u.f]) continue;
		genSub(u.f, node);
		sub[node]+=sub[u.f];
	}
}

int getCen(int node, int tot_sz, int p = -1){
	for(auto u: adj[node]){
		if(u.f == p || done[u.f]) continue;
		if(sub[u.f] > tot_sz/2) return getCen(u.f, tot_sz, node);
	}
	return node;
}



int genCen(int node){
	cen_nodes.clear();
	genSub(node);
	return getCen(node, sub[node]);
}

pair<int, ll> par[mx];
ll sum_up[mx];
pair<ll, int> best_down[mx];

void genUpDown(int node, int p = -1){
	sum_up[node] = 0;
	best_down[node] = mp(0, node);

	for(auto u: adj[node]){
		if(u.f == p || done[u.f]) continue;
		ll bedge = 0;
		for(auto x: adj[u.f]){
			if(done[x.f]) continue;
			if(x.f == node){
				bedge = x.s;
				break;
			}
		}
		par[u.f] = mp(node, u.s);
		sum_up[node]+=bedge;
		genUpDown(u.f, node);
		sum_up[node]+=sum_up[u.f];
		best_down[node] = max(best_down[node], mp(best_down[u.f].f+u.s, best_down[u.f].s));
	}
}

bool taken[mx];

void genAns(int cen, ll offset){
	cen = genCen(cen);

	//process cen

	genUpDown(cen);

	//update ans - remember done/offset

	//cout << "cen, offset, sumup[cen]: " << cen << " " << offset << " " << sum_up[cen] << "\n";

	ckmax(ans[1], sum_up[cen]+offset);

	priority_queue<pair<ll, int>> pq;
	for(auto u: adj[cen]){
		if(done[u.f]) continue;
		pq.push(mp(best_down[u.f].f+par[u.f].s, best_down[u.f].s));
	}

	for(auto u: cen_nodes){
		taken[u] = 0;
	}
	taken[cen] = 1;

	ll cur_sum = 0;
	ll best_outside = 0;
	bool good = 0;
	for(int i = 1; i <= sz(cen_nodes); i++){
		if(sz(pq) == 0){
			ckmax(ans[i], cur_sum+sum_up[cen]+offset);
			continue;
		}
		int take_node = pq.top().s;
		pq.pop();

		//cout << "take_node: " << i << " " << take_node << "\n";
		while(true){
			cur_sum+=par[take_node].s;
			taken[take_node] = 1;
			//cout << "add: " << take_node << " " << par[take_node].s << "\n";
			for(auto u: adj[take_node]){
				if(done[u.f] || taken[u.f] || u.f == par[take_node].f) continue;
				pq.push(mp(best_down[u.f].f+par[u.f].s, best_down[u.f].s));
				//cout << "push: " << best_down[u.f].s << "\n";
			}
			if(taken[par[take_node].f]) break;
			take_node = par[take_node].f;
		}
		
		if(i == 1){
			for(auto u: adj[cen]){
				if(done[u.f]) continue;
				if(u.f != take_node){
					ckmax(best_outside, u.s+best_down[u.f].f);
				}
			}
		}

		if(i != 1 && par[take_node].f == cen){
			good = 1;
		}

		if(good){
			ckmax(ans[i], cur_sum+sum_up[cen]+offset);
			//cout << "ckmax(ans[]: " << i << " " << cur_sum+sum_up[cen]+offset << "\n";
		}
		else{
			ckmax(ans[i+1], cur_sum+best_outside+sum_up[cen]+offset);
			//cout << "ckmax(ans[]: " << i+1 << " " << cur_sum+best_outside+sum_up[cen]+offset << "\n";
		}
	}

	//recurse

	done[cen] = 1;

	vector<pair<int, ll>> recurse;
	for(auto u: adj[cen]){
		if(done[u.f]) continue;
		ll new_offset = offset+sum_up[cen]-sum_up[u.f]+u.s;
		for(auto x: adj[u.f]){
			if(x.f == cen){
				new_offset-=x.s;
				break;
			}
		}
		recurse.pb(mp(u.f, new_offset));
	}

	for(auto u: recurse){
		genAns(u.f, u.s);
	}
}

int main(){
	cin >> N;
	for(int i = 1; i <= N-1; i++){
		cin >> A[i] >> B[i] >> C[i] >> D[i];
		adj[A[i]].pb(mp(B[i], C[i]));
		adj[B[i]].pb(mp(A[i], D[i]));
		tot_cost+=C[i]+D[i];
	}

	genAns(1, 0);

	// cout << "tot: " << tot_cost << "\n";
	// for(int i = 1; i <= N; i++){
	// 	cout << "i, ans[i]: " << i << " " << ans[i] << "\n";
	// }

	for(int i = 1; i <= N; i++){
		ans[i] = tot_cost-ans[i];
	}

	//cout << ans[N] << "\n";

	assert(ans[N] == 0);

	int Q;
	cin >> Q;
	for(int i = 1; i <= Q; i++){
		cin >> E[i];
		cout << ans[E[i]] << "\n";
	}
}
#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...