제출 #620245

#제출 시각아이디문제언어결과실행 시간메모리
620245ZaniteDynamic Diameter (CEOI19_diameter)C++17
100 / 100
352 ms65552 KiB
#include <bits/stdc++.h>
using namespace std;

using ll	= long long;
using pll	= pair<ll, ll>;
using Edge	= pair<ll, pll>;

#define fi	first
#define se	second

const int maxN	= 1e5 + 5;

const ll INF	= 1e18;

ll n, q, w;
vector<pll> adj[maxN];
vector<Edge> edges;

ll timer;
ll dist[maxN], tin[maxN], tout[maxN];
vector<ll> Euler(1);

void dfs(ll cur, ll par, ll cdist) {
	dist[cur] = cdist;
	Euler.push_back(cur);
	tin[cur] = (ll)Euler.size() - 1;

	for (auto &[nxt, w] : adj[cur]) {
		if (nxt == par) continue;
		dfs(nxt, cur, cdist+w);

		Euler.push_back(cur);
	}

	tout[cur] = (ll)Euler.size() - 1;
}

struct Segtree {
	struct Node {
		// max(dist[x] - 2dist[y] + dist[z])
		// A = dist[x] or dist[z]
		// B = -2dist[y]

		ll A, B, AB, BA, ABA, lazy;

		Node() {}

		Node(ll val) {
			A = val;
			B = -2ll * val;
			AB = BA = ABA = -INF;
			lazy = 0;
		}

		void print() {
			#define _ << ' ' <<
			cout << A _ B _ AB _ BA _ ABA _ lazy << '\n';
		}
	};

	ll sz;
	vector<Node> seg;

	Segtree(ll sz) : sz(sz) {
		seg.assign((sz << 2) + 1, Node());
	}

	void updateNode(ll pos, ll val) {
		Node &C = seg[pos];

		C.A += val;
		C.B -= 2ll * val;
		C.AB -= val;
		C.BA -= val;
		C.lazy += val;
	}

	void checkLazy(ll pos) {
		if (seg[pos].lazy != 0) {
			ll lc = pos << 1, rc = lc | 1;
			updateNode(lc, seg[pos].lazy);
			updateNode(rc, seg[pos].lazy);
			seg[pos].lazy = 0;
		}
	}

	Node merge(Node L, Node R) {
		Node N = Node(0);

		N.A = max(L.A, R.A);
		N.B = max(L.B, R.B);

		N.AB = max({
			L.AB,
			R.AB,
			L.A + R.B
		});

		N.BA = max({
			L.BA,
			R.BA,
			L.B + R.A
		});

		N.ABA = max({
			L.ABA,
			R.ABA,
			L.A + R.BA,
			L.AB + R.A
		});

		//cout << "Merged:\n";
		//L.print(); R.print(); N.print();

		return N;
	}

	void build(ll pos, ll l, ll r) {
		if (l == r) {
			//cerr << pos << ' ' << l << ' ' << Euler[l] << ' ' << dist[Euler[l]] << '\n';
			seg[pos] = Node(dist[Euler[l]]);
			return;
		}

		ll m = (l+r) >> 1, lc = pos << 1, rc = lc | 1;
		build(lc, l, m);
		build(rc, m+1, r);
		seg[pos] = merge(seg[lc], seg[rc]);
	}
	void build() {build(1, 1, sz);}

	void update(ll pos, ll l, ll r, ll ul, ll ur, ll val) {
		if (l > r || ul > ur || l > ur || ul > r) return;
		if (ul <= l && r <= ur) {
			updateNode(pos, val);
			return;
		}

		checkLazy(pos);

		ll m = (l+r) >> 1, lc = pos << 1, rc = lc | 1;
		update(lc, l, m, ul, ur, val);
		update(rc, m+1, r, ul, ur, val);
		seg[pos] = merge(seg[lc], seg[rc]);
	}
	void update(ll ul, ll ur, ll val) {update(1, 1, sz, ul, ur, val);}

	ll query(ll pos, ll l, ll r, ll idx) {
		cerr << pos << ' ' << l << ' ' << r << ' ' << idx << '\n';
		if (l == r) {
			return seg[pos].A;
		}

		checkLazy(pos);

		ll m = (l+r) >> 1, lc = pos << 1, rc = lc | 1;
		if (idx <= m) {
			return query(lc, l, m, idx);
		} else {
			return query(rc, m+1, r, idx);
		}
	}

	ll query() {
		return max({seg[1].ABA, seg[1].AB, seg[1].BA});
	}

	void print() {
		for (ll i = 1; i <= sz; i++) {
			cout << query(1, 1, sz, i) << ' ';
		}
		cout << '\n';
	}

	void print2() {
		for (ll i = 1; i <= 13; i++) {cout << i << ": "; seg[i].print();}
		cout << "\n";
	}
};

int main() {
	scanf("%lld %lld %lld", &n, &q, &w);
	for (ll a, b, c, i = 1; i < n; i++) {
		scanf("%lld %lld %lld", &a, &b, &c);
		adj[a].push_back({b, c});
		adj[b].push_back({a, c});

		edges.push_back({c, {a, b}});
	}
	dfs(1, 0, 0);

	//for (auto i : Euler) {cout << i << ' ';} cout << '\n';

	ll ES = (ll)Euler.size() - 1;
	/*
	for (ll i = 1; i <= n; i++) {
		cout << tin[i] << ' ' << tout[i] << ' ' << dist[i] << '\n';
	}
	*/

	Segtree S(ES);
	S.build();
	for (auto &[cw, p] : edges) {
		if (tin[p.se] < tin[p.fi]) {swap(p.fi, p.se);}
	}

	ll last = 0;
	for (ll d, e, i = 1; i <= q; i++) {
		scanf("%lld %lld", &d, &e);
		d = (d + last) % (n - 1);
		e = (e + last) % w;

		//cout << d << ' ' << e << '\n';

		auto &[cw, p] = edges[d];

		S.update(tin[p.se], tout[p.se], e - cw);
		cw = e;

		//S.print2();

		last = S.query();
		printf("%lld\n", last);
	}
}

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

diameter.cpp: In function 'int main()':
diameter.cpp:182:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  182 |  scanf("%lld %lld %lld", &n, &q, &w);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:184:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  184 |   scanf("%lld %lld %lld", &a, &b, &c);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:209:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  209 |   scanf("%lld %lld", &d, &e);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...