Submission #1243770

#TimeUsernameProblemLanguageResultExecution timeMemory
1243770justinlgl20Two Currencies (JOI23_currencies)C++20
100 / 100
1073 ms60744 KiB
#include <bits/stdc++.h>
using namespace std;
 
#define int long long
 
#define all(x) (x).begin(), (x).end()
 
template<template<typename> class Container, typename G>
ostream& operator<<(ostream& os, Container<G> x) {
    int f = 0; os << '{'; for (auto &i: x) os << (f++ ? ", " : ""), os << i; os << "}";
    return os;
}
 
void _print() {cerr << "]\n";}
 
template<typename T, typename... V>
void _print(T t, V... v) {cerr << t; if (sizeof...(v)) cerr <<", "; _print(v...);}
 
#ifdef DEBUG
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif

#define pii pair<int, int>
#define f first
#define s second

namespace ds{
	const int n=100005;
	const int SQ=300;
	int cnt[(n/SQ)+5],sm[(n/SQ)+5],cn[n],smm[n];
	vector<int>c;unordered_map<int,int>comp;
	void init(){
		sort(all(c));
		c.resize(unique(all(c))-c.begin());
		for(int i=0;i<c.size();i++){
			comp[c[i]]=i;
		}
	}
	int query(int v){
		//given that we can use up to v silvers, returns how many things are leftover
		dbg(v);
		int cur=0,pos=0,c=0;
		for(int i=0;i<n/SQ and pos<ds::c.size();i++){
			if(cur+sm[i]<=v){
				cur+=sm[i];
				c+=cnt[i];
				pos+=SQ;
			}else{
				break;
			}
		}
		for(int i=0;i<SQ and pos<ds::c.size();i++){
			if(cur+smm[pos]<=v){
				cur+=smm[pos];
				c+=(cn[pos]);
				pos++;
			}else{
				break;
			}
		}
		dbg("HI",v,cur,ds::c[pos],pos);
		while(pos<ds::c.size() and cur+ds::c[pos]<=v){
			cur+=ds::c[pos];
			c++;
		}
		return c;
	}
	void add(int v){
		int real=c[v];
		//dbg("ADD",real);
		int bucket=v/SQ;
		smm[v]+=real;
		cn[v]++;
		sm[bucket]+=real;
		cnt[bucket]++;
	}
	void remove(int v){
		int real=c[v];
		//dbg("REM",real);
		int bucket=v/SQ;
		smm[v]-=real;
		cn[v]--;
		sm[bucket]-=real;
		cnt[bucket]--;
	}
}

vector<int>adj[100005];
pii e[100005];
vector<int> things[100005];
int depth[100005],tin[100005],tbitin[100005],tmid[100005],tout[100005],w[100005];
vector<int>v;

void d(int u,int p=-1){for(int i:adj[u]){if(i==p)continue;depth[i]=depth[u]+1;d(i,u);}}
int jmp[100006][20],ts[100005],pmo[100005];
int counter=0;

void dfs(int u,int p=-1){
	ts[u]=counter++;
	jmp[u][0]=p;
	for(int i=1;i<20;i++){
		if(jmp[u][i-1]!=-1){
			jmp[u][i]=jmp[jmp[u][i-1]][i-1];
		}
	}
	tin[u]=v.size();
	dbg(u,things[u],adj[u]);
	for(auto i:things[u]){ v.push_back(i); }
	tbitin[u]=v.size();
	for(int i:adj[u]){
		if(i==p)continue;
		depth[i]=depth[u]+1;
		dfs(i,u);
	}
	tmid[u]=v.size();
	for(auto i:things[u]){ v.push_back(i); }
	tout[u]=v.size();
	pmo[u]=counter++;
}

bool is_anc(int a,int b){
	return ts[a]<=ts[b] and pmo[b]<=pmo[a];
}

int lca(int a,int b){
	if(is_anc(a,b))return a;
	if(is_anc(b,a))return b;
	return 1;
}

int dist(int u,int v){
	return depth[u]+depth[v]-2*depth[lca(u,v)];
}

inline int64_t hilbertOrder(int x, int y, int pow, int rotate) {
	if (pow == 0) { return 0; }
	int hpow = 1 << (pow-1);
	int seg = (x < hpow) ? ( (y < hpow) ? 0 : 3) : ( (y < hpow) ? 1 : 2);
	seg = (seg + rotate) & 3;
	const int rotateDelta[4] = {3, 0, 0, 1};
	int nx = x & (x ^ hpow), ny = y & (y ^ hpow);
	int nrot = (rotate + rotateDelta[seg]) & 3;
	int64_t subSquareSize = int64_t(1) << (2*pow - 2);
	int64_t ans = seg * subSquareSize;
	int64_t add = hilbertOrder(nx, ny, pow-1, nrot);
	ans += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
	return ans;
}

struct query{
	int l,r,s,t,x,y,ans,val,inx;
	bool operator<(query &other){
		return val<other.val;	
	}
};
query q[100005];

int32_t main(){
	int n,m,qq;cin>>n>>m>>qq;
	for(int i=0;i<n-1;i++){cin>>e[i].f>>e[i].s;adj[e[i].f].push_back(e[i].s);adj[e[i].s].push_back(e[i].f);}
	d(1);

	for(int i=0;i<n-1;i++){if(depth[e[i].f]>depth[e[i].s])swap(e[i].f,e[i].s);}
	for(int i=0;i<m;i++){int p,v;cin>>p>>v;p--;things[e[p].s].push_back(i);::w[i]=v;dbg(e[p].s,w[i]);ds::c.push_back(w[i]);}
	ds::init();
	for(int i=0;i<m;i++)w[i]=ds::comp[w[i]];
	for(int i=1;i<=n;i++){
		dbg(i,things[i]);
	}
	dfs(1);
	dbg(::v);
	dbg(qq);
	for(int i=0;i<qq;i++){
		dbg(i);
		cin>>q[i].s>>q[i].t>>q[i].x>>q[i].y;q[i].inx=i;
		//if(tin[q[i].s]>tin[q[i].t])swap(q[i].s,q[i].t);
		if(ts[q[i].s]>ts[q[i].t])swap(q[i].s,q[i].t);
		// s is higher
		//if(tin[q[i].s]<=tin[q[i].t] and tout[q[i].t]<=tout[q[i].s]){
		if(is_anc(q[i].s,q[i].t)){
			q[i].l=tbitin[q[i].s];q[i].r=tbitin[q[i].t]-1;
		}else{
			q[i].l=tmid[q[i].s];q[i].r=tbitin[q[i].t]-1;
		}
		dbg(q[i].s,q[i].t,q[i].l,q[i].r);
		q[i].val=hilbertOrder(q[i].l,q[i].r,20,0);
	}
	sort(q,q+qq);
	vector<int>cnt(m);
	int l=0,r=0;cnt[v[0]]++;ds::add(w[v[0]]);
	//set<int>s;s.insert(v[0]);
	int pathlen=1;
	function<void(int)>add=[&](int i){
		cnt[i]++;
		if(cnt[i]==1){ds::add(w[i]);pathlen++;}//s.insert(i);}
		if(cnt[i]==2){ds::remove(w[i]);pathlen--;}//s.erase(s.find(i));}
	};
	function<void(int)>rem=[&](int i){
		if(cnt[i]==2){ds::add(w[i]);pathlen++;}//s.insert(i);}
		if(cnt[i]==1){ds::remove(w[i]);pathlen--;}//s.erase(s.find(i));}
		cnt[i]--;
	};
	vector<int>ans(qq);
	for(int i=0;i<qq;i++){
		dbg(i,q[i].l,q[i].r,q[i].s,q[i].t);
		while(l>q[i].l){
			l--; add(v[l]);
		}
		while(r<q[i].r){
			r++; add(v[r]);
		}
		while(l<q[i].l){
			rem(v[l]);l++;
		}
		while(r>q[i].r){
			rem(v[r]);r--;
		}
		auto idk=ds::query(q[i].y);//this is min golds needed
		//int pathlen=dist(q[i].s,q[i].t);// dist between q[i].s and q[i].t in terms of edges
		//int pathlen=s.size();
		dbg(pathlen,idk);
		q[i].ans=q[i].x-(pathlen-idk);
		if(q[i].ans<0)q[i].ans=-1;
		ans[q[i].inx]=q[i].ans;
	}
	for(int i=0;i<qq;i++){
		cout<<ans[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...