Submission #1336114

#TimeUsernameProblemLanguageResultExecution timeMemory
1336114NAMINTwo Currencies (JOI23_currencies)C++20
100 / 100
1215 ms37420 KiB
#include <bits/stdc++.h>
#define ll long long
#define endl "\n"
using namespace std;

struct Fensum{
	ll len=1;
	vector<ll> tree;
	Fensum(int l){
		len=l+1;
		tree=vector<ll>(len+1,0);
	}

	void update(int idx,ll v){
		idx++;
		while(idx<=len){
			tree[idx]+=v;
			idx+=(idx&-idx);
		}
	}

	ll query(int idx){
		idx++;
		ll res = 0;
		while(idx>=1){
			res += tree[idx];
			idx-=(idx&-idx);
		}
		return res;
	}
};

const int LOG = 20;
const int mxN = 100001;
int N,M,Q;
vector<int> adj[mxN];
vector<pair<int,int>> edges;
vector<int> depth(mxN,0);
vector<int> sub_sz(mxN,1);
vector<int> in(mxN,0);
vector<int> ot(mxN,0);
vector<int> parent(mxN,-1);
int jump[mxN][LOG];

int timer;
void dfs(int node,int p=-1){
	parent[node]=p;
	in[node]=timer++;
	for(int u : adj[node]){
		if(u==p)
			continue;
		depth[u]=depth[node]+1;
		dfs(u,node);
		sub_sz[node]+=sub_sz[u];
	}
	ot[node]=timer++;
}

ll get_sum(int node,int parent,Fensum &fen){
	return fen.query(in[node])-fen.query(in[parent]);
}

void activate(int node,ll v,Fensum &fen){
	fen.update(in[node],v);
	fen.update(ot[node],-v);
}

void init_lca(){
	for(int i=0;i<mxN;i++){
		for(int e=0;e<LOG;e++){
			jump[i][e]=-1;
		}
	}
	for(int u=0;u<mxN;u++){
		jump[u][0]=parent[u];
	}
	
	for(int e=1;e<LOG;e++){
		for(int u=0;u<mxN;u++){
			if(jump[u][e-1]!=-1)
				jump[u][e]=jump[jump[u][e-1]][e-1];
		}
	}
}

int lca(int a,int b){
	if(depth[a]<depth[b])
		swap(a,b);
	int k = depth[a]-depth[b];
	for(int e=LOG-1;e>=0;e--){
		if((1<<e)&k){
			a=jump[a][e];
		}
	}

	if(a==b)
		return a;
	
	for(int e=LOG-1;e>=0;e--){
		int u = jump[a][e],v = jump[b][e];
		if(u!=v){
			a=u,b=v;
		}
	}
	return parent[a];
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	timer=0;

	cin >> N >> M >> Q;
	for(int i=0;i<N-1;i++){
		int u,v;
		cin >> u >> v;
		u--,v--;
		adj[u].push_back(v);
		adj[v].push_back(u);
		edges.push_back(make_pair(u,v));
	}
	dfs(0);
	for(int i=0;i<N-1;i++){
		int u=edges[i].first,v=edges[i].second;
		if(depth[u]>depth[v])
			swap(edges[i].first,edges[i].second);
	}
	
	vector<pair<ll,int>> op;//cost,node
	vector<int> nbop(N,0);
	for(int i=0;i<M;i++){
		ll idx_arr,cost;
		cin >> idx_arr >> cost;
		idx_arr--;
		op.push_back(make_pair(cost,edges[idx_arr].second));
	}
	sort(op.begin(),op.end());

	vector<ll> s(Q),e(Q),gold(Q),silver(Q);
	for(int i =0;i<Q;i++){
		cin >> s[i] >> e[i] >> gold[i] >> silver[i];
		s[i]--,e[i]--;
	}
	init_lca();
	vector<int> lo(Q,0);
	vector<int> hi(Q,M);

	for(int _=0;_<20;_++){
		Fensum fen_act(3*N+1);
		vector<pair<int,int>> mid;
		for(int q=0;q<Q;q++){
			mid.push_back(make_pair(lo[q]+(hi[q]-lo[q]+1)/2,q));
		}
		sort(mid.rbegin(),mid.rend());
		
		for(int k=0;k<=M;k++){//k:=nb activé
			if(k>0)
				activate(op[k-1].second,op[k-1].first,fen_act);
			while(mid.size()>0&&mid.back().first==k){
				int q = mid.back().second;
				int u = s[q],v = e[q];
				if(depth[u]>depth[v])
					swap(u,v);
				int z = lca(u,v);
				ll cost = get_sum(v,z,fen_act);
				if(z!=u)//different path
					cost+=get_sum(u,z,fen_act);

				if(cost<=silver[q])
					lo[q]=k;
				else
					hi[q]=k;
				mid.pop_back();
			}
		}
	}

	vector<pair<int,int>> k_mx;
	for(int q=0;q<Q;q++){
		k_mx.push_back(make_pair(lo[q],q));
	}
	sort(k_mx.rbegin(),k_mx.rend());
	
	vector<ll> ans(Q,-1);
	Fensum fen_cnt(3*N+1);
	for(int i=0;i<M;i++){
		activate(op[i].second,1,fen_cnt);
	}
	Fensum fen_curcnt(3*N+1);
	
	for(int k=0;k<=M;k++){
		if(k>0)
			activate(op[k-1].second,1,fen_curcnt);

		while(k_mx.size()>0&&k_mx.back().first==k){
			int q = k_mx.back().second;
			int u = s[q],v = e[q];
			if(depth[u]>depth[v])
				swap(u,v);
			int z = lca(u,v);
			ll C = get_sum(v,z,fen_cnt);
			if(z!=u)//different path
				C+=get_sum(u,z,fen_cnt);

			ll curC = get_sum(v,z,fen_curcnt);
			if(z!=u)//different path
				curC+=get_sum(u,z,fen_curcnt);
			if(gold[q]-(C-curC)>=0)
				ans[q]=gold[q]-(C-curC);
			k_mx.pop_back();
		}
	}

	for(int i=0;i<Q;i++){
		cout << ans[i] << endl;
	}
}


#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...