제출 #763261

#제출 시각아이디문제언어결과실행 시간메모리
763261MetalPowerTwo Currencies (JOI23_currencies)C++14
100 / 100
948 ms39484 KiB
#include <bits/stdc++.h>
using namespace std;

const int MX = 1e5 + 10;

#define ll long long
#define pii pair<int, int>
#define pli pair<ll, int>
#define fi first
#define se second

// parallel binser + hld

struct segtree{
	pli st[MX << 1];

	void build(){
		for(int i = 0; i < (MX << 1); i++) st[i] = {0ll, 0};
	}

	void upd(int p, int v){
		for(p += MX, st[p].fi += v, st[p].se += 1, p >>= 1; p > 0; p >>= 1){
			st[p].fi = st[p << 1].fi + st[p << 1|1].fi;
			st[p].se = st[p << 1].se + st[p << 1|1].se;
		}
	}

	pli que(int l, int r){
		pli res = {0, 0};
		for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){
			if(l & 1){
				res.fi += st[l].fi, res.se += st[l].se;
				l++;
			}
			if(r & 1){
				--r;
				res.fi += st[r].fi, res.se += st[r].se;
			}
		}
		return res;
	}
} S;

struct hld{
	int sz[MX], dep[MX], par[MX], in[MX], out[MX], head[MX], tim = 0;
	vector<int> adj[MX];

	void ae(int u, int v){
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	void dfs(int u, int v){
		if(v != 0) adj[u].erase(find(adj[u].begin(), adj[u].end(), v));

		par[u] = v;
		dep[u] = dep[v] + 1;
		sz[u] = 1;

		for(int& nx : adj[u]){
			dfs(nx, u);
			sz[u] += sz[nx];
			if(sz[nx] > sz[adj[u][0]]) swap(nx, adj[u][0]);
		}
	}

	void dfs2(int u, int v){
		in[u] = ++tim;
		for(int nx : adj[u]){
			if(nx == adj[u][0]) head[nx] = head[u];
			else head[nx] = nx;
			dfs2(nx, u);
		}
		out[u] = tim;
	}

	void init(){
		dfs(1, 0);
		head[1] = 1;
		dfs2(1, 0);
	}

	void upd(int nd, int v){
		S.upd(in[nd], v);
	}

	pli que(int u, int v){
		pli res = {0, 0};
		for(; head[u] != head[v]; v = par[head[v]]){
			if(dep[head[u]] > dep[head[v]]) swap(u, v);
			pli nw = S.que(in[head[v]], in[v]);
			res.fi += nw.fi, res.se += nw.se;
		}
		if(dep[u] > dep[v]) swap(u, v);
		pli nw = S.que(in[u] + 1, in[v]);
		res.fi += nw.fi, res.se += nw.se;
		return res;
	}
} H;

struct query{
	int s, t, x; ll y; int l, r, mid, id;

	query(int s = 0, int t = 0, int x = 0, ll y = 0, int l = 0, int r = 0, int id = 0) : 
		s(s), t(t), x(x), y(y), l(l), r(r), mid(l + r >> 1), id(id) {}

	bool operator < (const query other) const {
		return mid < other.mid;
	}
};

vector<query> queries[2];

int N, M, Q; pli ans[MX];
vector<pii> edges, ch;

int qs[MX], qt[MX], X[MX]; ll Y[MX];

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

	cin >> N >> M >> Q;
	for(int i = 1; i < N; i++){
		int u, v; cin >> u >> v;
		edges.push_back({u, v});
		H.ae(u, v);
	}

	for(int i = 0; i < M; i++){
		int p, c; cin >> p >> c; p--;
		ch.push_back({c, p});
	}

	sort(ch.begin(), ch.end());

	// cout << "init\n";
	H.init();

	for(int i = 0; i < N - 1; i++){
		if(H.dep[edges[i].fi] > H.dep[edges[i].se]) swap(edges[i].fi, edges[i].se);
	}

	for(int i = 0; i < Q; i++){
		int s, t, x; ll y; cin >> s >> t >> x >> y; qs[i] = s, qt[i] = t, X[i] = x, Y[i] = y;
		query curr = query(s, t, x, y, 0, M, i); 
		// 0 is none, 1 is index 0, 2 is index 0 to 1, ..., M is index 0 to M-1
		queries[0].push_back(curr);
	}

	int id = 0;
	sort(queries[0].begin(), queries[0].end());
	S.build();

	for(; !queries[id].empty(); ){
		int j = 0;
		// cout << "query " << id << '\n';
		for(query& curr : queries[id]){
			for(; j < M && j < curr.mid; j++) H.upd(edges[ch[j].se].se, ch[j].fi);
			pli nw = H.que(curr.s, curr.t);
			// cout << "at j " << curr.mid << " from " << curr.s << " to " << curr.t << " " << nw.fi << '\n';
			if(nw.fi <= curr.y){
				ans[curr.id] = nw;
				query nx = query(curr.s, curr.t, curr.x, curr.y, curr.mid + 1, curr.r, curr.id);
				if(nx.l <= nx.r) queries[id ^ 1].push_back(nx);
			}else{
				query nx = query(curr.s, curr.t, curr.x, curr.y, curr.l, curr.mid - 1, curr.id);
				if(nx.l <= nx.r) queries[id ^ 1].push_back(nx);
			}
		}
		queries[id].clear();
		id ^= 1;
		sort(queries[id].begin(), queries[id].end());
		S.build();
	}

	for(int i = 0; i < M; i++) H.upd(edges[ch[i].se].se, 1);

	for(int i = 0; i < Q; i++){
		// cout << "found " << ans[i].fi << " " << ans[i].se << '\n';
		int used_gold = H.que(qs[i], qt[i]).se - ans[i].se;
		assert(ans[i].fi <= Y[i]);
		if(used_gold > X[i]) cout << -1 << '\n';
		else cout << X[i] - used_gold << '\n';
	}
}

컴파일 시 표준 에러 (stderr) 메시지

currencies.cpp: In constructor 'query::query(int, int, int, long long int, int, int, int)':
currencies.cpp:105:45: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  105 |   s(s), t(t), x(x), y(y), l(l), r(r), mid(l + r >> 1), id(id) {}
      |                                           ~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...