Submission #1004760

#TimeUsernameProblemLanguageResultExecution timeMemory
1004760pccTwo Currencies (JOI23_currencies)C++17
100 / 100
1624 ms95936 KiB
#include <bits/stdc++.h>
using namespace std;

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,popcnt,sse4")

#define ll long long
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fs first
#define sc second
#define tlll tuple<ll,ll,ll>


const int mxn = 1e5+10;
vector<int> tree[mxn];
int par[mxn],link_top[mxn],sz[mxn],bs[mxn],idx[mxn],dep[mxn],cnt;
vector<ll> roads[mxn];
int N,M,Q;
vector<ll> all;
pii edges[mxn];

struct SEG{
#define ls now*2+1
#define rs now*2+2
#define mid ((l+r)>>1)
	vector<pll> seg[mxn*4];
	void build(int now,int l,int r){
		if(l == r){
			for(auto &i:roads[l])seg[now].push_back(pll(i,0));
		}
		else{
			build(ls,l,mid);
			build(rs,mid+1,r);
			for(int i = 1;i<seg[ls].size();i++)seg[now].push_back(pll(seg[ls][i].fs,0));
			for(int i = 1;i<seg[rs].size();i++)seg[now].push_back(pll(seg[rs][i].fs,0));
		}
		seg[now].push_back(pll(0,0));
		sort(seg[now].begin(),seg[now].end());
		for(int i = 1;i<seg[now].size();i++)seg[now][i].sc = seg[now][i-1].sc+seg[now][i].fs;
		return;
	}
	vector<int> getrange(int now,int l,int r,int s,int e){
		if(l>=s&&e>=r){
			return {now};
		}
		if(mid>=e)return getrange(ls,l,mid,s,e);
		else if(mid<s)return getrange(rs,mid+1,r,s,e);
		else{
			auto tl = getrange(ls,l,mid,s,e);
			auto tr = getrange(rs,mid+1,r,s,e);
			if(tl.size()>tr.size())for(auto &i:tr)tl.push_back(i);
			else for(auto &i:tl)tr.push_back(i);
			return (tl.size()>tr.size()?tl:tr);
		}
	}
#undef ls
#undef rs
#undef mid
};

void dfs1(int now){
	sz[now] = 1;
	for(auto nxt:tree[now]){
		if(nxt == par[now])continue;
		par[nxt] = now;
		dep[nxt] = dep[now]+1;
		dfs1(nxt);
		sz[now] += sz[nxt];
		if(!bs[now]||sz[bs[now]]<sz[nxt])bs[now] = nxt;
	}
	return;
}

void dfs2(int now,int top){
	link_top[now] = top;
	idx[now] = ++cnt;
	if(bs[now])dfs2(bs[now],top);
	for(auto nxt:tree[now]){
		if(nxt == par[now]||nxt == bs[now])continue;
		dfs2(nxt,nxt);
	}
	return;
}

SEG seg;

vector<int> LCA(int a,int b){
	vector<int> re;
	int ta = link_top[a],tb = link_top[b];
	while(ta != tb){
		if(dep[ta]<dep[tb]){
			swap(a,b);
			swap(ta,tb);
		}
		auto tv = seg.getrange(0,1,N,idx[ta],idx[a]);
		for(auto &i:tv)re.push_back(i);
		a = par[ta];
		ta = link_top[a];
	}
	if(dep[a]>dep[b])swap(a,b);
	if(a != b){
		auto tv = seg.getrange(0,1,N,idx[a]+1,idx[b]);
		for(auto &i:tv)re.push_back(i);
	}
	return re;
}

pll getall(vector<int>& ids,ll lim){
	pll re = pll(0,0);
	for(auto &i:ids){
		auto p = lower_bound(seg.seg[i].begin(),seg.seg[i].end(),pll(lim+1,-1))-seg.seg[i].begin();
		assert(p);
		re.fs += seg.seg[i][p-1].sc;
		re.sc += seg.seg[i].size()-p;
	}
	return re;
}

void solve(int s,int t,ll gold,ll silv){
	vector<int> ids = LCA(s,t);
	int l = 0,r = all.size()-1;
	while(l != r){
		int mid = (l+r+1)>>1;
		if(getall(ids,all[mid]).fs>silv)r = mid-1;
		else l = mid;
	}
	ll ans = -1;
	//cout<<all[l]<<":"<<getall(ids,all[l]).fs<<','<<getall(ids,all[l]).sc<<"\n";
	if(l == all.size()-1)ans = max(ans,gold-getall(ids,all[l]).sc);
	else{
		pll ta = getall(ids,all[l]);
		pll tb = getall(ids,all[l+1]);
		silv -= ta.fs;
		//cout<<all[l]<<' '<<all[l+1]<<','<<ta.fs<<" "<<ta.sc<<','<<tb.fs<<' '<<tb.sc<<'\n';
		gold = max(-1ll,gold-(ta.sc-min(silv/all[l+1],ta.sc-tb.sc)));
		ans = gold;
	}
	cout<<ans<<'\n';
	return;
}

int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>N>>M>>Q;
	for(int i = 1;i<N;i++){
		int a,b;
		cin>>a>>b;
		edges[i] = pii(a,b);
		tree[a].push_back(b);
		tree[b].push_back(a);
	}
	par[1] = 1;
	dfs1(1);
	dfs2(1,1);
	assert(cnt == N);
	for(int i = 0;i<M;i++){
		ll p,val;
		cin>>p>>val;
		all.push_back(val);
		auto &[a,b] = edges[p];
		if(dep[a]>dep[b])swap(a,b);
		assert(dep[b]-dep[a] == 1);
		roads[idx[b]].push_back(val);
	}
	all.push_back(0);
	sort(all.begin(),all.end());all.resize(unique(all.begin(),all.end())-all.begin());
	seg.build(0,1,N);
	while(Q--){
		ll s,t,gold,silv;
		cin>>s>>t>>gold>>silv;
		solve(s,t,gold,silv);
	}
}

Compilation message (stderr)

currencies.cpp: In member function 'void SEG::build(int, int, int)':
currencies.cpp:35:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   35 |    for(int i = 1;i<seg[ls].size();i++)seg[now].push_back(pll(seg[ls][i].fs,0));
      |                  ~^~~~~~~~~~~~~~~
currencies.cpp:36:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   36 |    for(int i = 1;i<seg[rs].size();i++)seg[now].push_back(pll(seg[rs][i].fs,0));
      |                  ~^~~~~~~~~~~~~~~
currencies.cpp:40:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   40 |   for(int i = 1;i<seg[now].size();i++)seg[now][i].sc = seg[now][i-1].sc+seg[now][i].fs;
      |                 ~^~~~~~~~~~~~~~~~
currencies.cpp: In function 'void solve(int, int, long long int, long long int)':
currencies.cpp:130:7: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  130 |  if(l == all.size()-1)ans = max(ans,gold-getall(ids,all[l]).sc);
      |     ~~^~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...