제출 #1366597

#제출 시각아이디문제언어결과실행 시간메모리
1366597zitTwo Currencies (JOI23_currencies)C++20
100 / 100
2564 ms40208 KiB
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
/*__stO_stO_stO_stO_stO_stO_stO_zit_Orz_Orz_Orz_Orz_Orz_Orz_Orz__*/
		      #include<bits/stdc++.h>
			using namespace std;
			 #define name "zit"
	    using ll =   int  ;const ll MOD2=998244353; 
	    #define all(x,y) x.begin()+1, x.begin()+y+1
	    #define FOR(i,a,b) for(ll i=(a);i<=(b);++i)
	    using vl=vector<ll>; using pll=pair<ll,ll>;
	    const int maxn=1e5+5, MOD=1e9+7;
	    #define pb push_back
	    const long long INF = 2e18;ll n;
	    #define All(x) x.begin(),x.end()

ll P, Q;

vl adj[maxn];
vl par (maxn, 0), h (maxn), sz (maxn), pos (maxn);
vector <vl> st (maxn, vl (17, 0));

ll timer = 0;

ll dfs (ll u = 1) {
	sz[u] = 1;
	pos[u] = ++timer;

	for (auto & v : adj[u]) if (v != par[u]) {
		par[v] = u;
		st[v][0] = u;
		h[v] = h[u] + 1;
		sz[u] += dfs (v);
	}

	return sz[u];
}

void build () {
	FOR (j,1,16)
		FOR (i,1,n)
			st[i][j] = st[st[i][j - 1]][j - 1];
}

ll lift (ll u, ll step) {
	FOR (j,0,16) if (step >> j & 1) u = st[u][j];
	return u;
}

ll lca (ll u, ll v) {
	if (h[u] < h[v]) swap (u, v);

	u = lift (u, h[u] - h[v]);

	if (u == v) return u;

	for (ll j = 16; j >= 0; --j)
		if (st[u][j] != st[v][j])
			u = st[u][j], v = st[v][j];

	return par[u];
}

struct SegTree {
	ll n;
	vector<long long> st;

	SegTree () {}

	SegTree (ll _n) {
		n = _n;
		st.assign (4 * n + 5, 0);
	}

	void reset () {
		fill (All(st), 0);
	}

	void upd (ll id, ll l, ll r, ll pos, long long val) {
		if (l == r) {
			st[id] += val;
			return;
		}

		ll mid = l + r >> 1;

		if (pos <= mid) upd (id << 1, l, mid, pos, val);
		else upd (id << 1 | 1, mid + 1, r, pos, val);

		st[id] = st[id << 1] + st[id << 1 | 1];
	}

	long long get (ll id, ll l, ll r, ll u, ll v) {
		if (l > v || r < u) return 0;
		if (u <= l && r <= v) return st[id];

		ll mid = l + r >> 1;

		return get (id << 1, l, mid, u, v)
		     + get (id << 1 | 1, mid + 1, r, u, v);
	}

	void upd (ll pos, long long val) {
		upd (1, 1, n, pos, val);
	}

	long long get (ll l, ll r) {
		if (l > r) return 0;
		return get (1, 1, n, l, r);
	}
};

struct Station {
	ll e, f, c;
}; vector <Station> S (maxn);

struct qurey {
	ll s, t, x;
	long long y;
	ll id;
}; vector <qurey> q (maxn);

ll M;

void UPD (ll u, ll c, SegTree & seg) {
	seg.upd (pos[u], +c);
	seg.upd (pos[u] + sz[u], -c);
}

long long getPath (ll u, SegTree & seg) {
	return seg.get (1, pos[u]);
}

long long query (ll u, ll v, SegTree & seg) {
	return getPath (u, seg) + getPath (v, seg) - 2LL * getPath (lca (u, v), seg);
}

vl L(maxn), R(maxn), ans(maxn);

void solvePBS () {
	FOR(i,1,Q) {
		L[i] = 0;
		R[i] = P;
		ans[i] = -1;
	}

	bool changed = 1;

	while (changed) {
		changed = 0;

		vector<vl> bucket(P + 2);

		FOR(i,1,Q) if (L[i] <= R[i]) {
			ll mid = L[i] + R[i] >> 1;
			bucket[mid].pb(i);
			changed = 1;
		}

		SegTree seg(M);

		FOR(i,0,P) {
			if (i) {
				ll u = S[i].e, v = S[i].f, c = S[i].c;

				if (par[u] == v) UPD (u, c, seg);
				else if (par[v] == u) UPD (v, c, seg);
			}

			for (auto &id : bucket[i]) {
				if (query (q[id].s, q[id].t, seg) <= q[id].y) {
					ans[id] = i;
					L[id] = i + 1;
				}
				else R[id] = i - 1;
			}
		}
	}
}

void sibidi () {
	cin >> n;
	cin >> P;
	cin >> Q;

	M = n + 5;

	vector <pll> ed;
	for (ll i = 1; i < n; ++i) {
		ll u, v; cin >> u >> v;
		adj[u].pb (v);
		adj[v].pb (u);
		ed.pb ({u, v});
	}

	dfs ();
	build ();

	FOR (i,1,P) {
		ll p, c;
		cin >> p >> c;
		S[i] = {ed[p - 1].first, ed[p - 1].second, c};
	}

	sort (all (S, P), [&] (const Station & X, const Station & Y) {
		return X.c < Y.c;
	});

	FOR (i,1,Q) {
		ll s, t, gold;
		long long silver;
		cin >> s >> t >> gold >> silver;

		q[i] = {s, t, gold, silver, i};
	}

	solvePBS ();

	vector<vl> bucket(P + 1);

	FOR(i,1,Q) if (ans[i] != -1)
		bucket[ans[i]].pb(i);

	SegTree seg(M);

	vl total(Q + 1, 0), pref(Q + 1, 0);

	FOR(i,1,P) {
		ll u = S[i].e, v = S[i].f;

		if (par[u] == v) UPD (u, 1, seg);
		else if (par[v] == u) UPD (v, 1, seg);
	}

	FOR(i,1,Q)
		total[i] = query(q[i].s, q[i].t, seg);

	seg.reset();

	FOR(i,0,P) {
		if (i) {
			ll u = S[i].e, v = S[i].f;

			if (par[u] == v) UPD (u, 1, seg);
			else if (par[v] == u) UPD (v, 1, seg);
		}

		for (auto &id : bucket[i])
			pref[id] = query(q[id].s, q[id].t, seg);
	}

	FOR(i,1,Q) {
		if (ans[i] == -1) {
			cout << -1 << '\n';
			continue;
		}

		long long need = total[i] - pref[i];

		if (need > q[i].x) cout << -1 << '\n';
		else cout << q[i].x - need << '\n';
	}
}

signed main() {
	if (fopen(name".inp","r")) {
		freopen(name".inp","r",stdin);
		freopen(name".out","w",stdout);
	}

	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	ll _ = 1;
	while (_--) sibidi();

	return 0;
}

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

currencies.cpp: In function 'int main()':
currencies.cpp:266:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  266 |                 freopen(name".inp","r",stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:267:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  267 |                 freopen(name".out","w",stdout);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…