제출 #207973

#제출 시각아이디문제언어결과실행 시간메모리
207973E869120Dynamic Diameter (CEOI19_diameter)C++14
73 / 100
2432 ms59068 KiB
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <functional>
using namespace std;
#pragma warning (disable: 4996)

class LazySegmentTree {
public:
	int size_ = 1;
	vector<long long> dat, lazy;

	void init(int sz) {
		while (size_ <= sz) size_ *= 2;
		dat.resize(size_ * 2, 0);
		lazy.resize(size_ * 2, 0);
	}
	void refresh(int u) {
		if (u < size_) {
			lazy[u * 2 + 0] += lazy[u];
			lazy[u * 2 + 1] += lazy[u];
			lazy[u] = 0;
			dat[u] = max(dat[u * 2] + lazy[u * 2], dat[u * 2 + 1] + lazy[u * 2 + 1]);
		}
		else {
			dat[u] += lazy[u];
			lazy[u] = 0;
		}
	}
	void add_(int l, int r, long long x, int a, int b, int u) {
		if (l <= a && b <= r) { lazy[u] += x; return; }
		if (r <= a || b <= l) return;
		refresh(u);
		add_(l, r, x, a, (a + b) >> 1, u * 2);
		add_(l, r, x, (a + b) >> 1, b, u * 2 + 1);
		refresh(u);
	}
	void add(int l, int r, long long x) {
		add_(l, r, x, 0, size_, 1);
	}
	long long query_(int l, int r, int a, int b, int u) {
		if (l <= a && b <= r) return dat[u] + lazy[u];
		if (r <= a || b <= l) return -(1LL << 60);
		refresh(u);
		long long v1 = query_(l, r, a, (a + b) >> 1, u * 2);
		long long v2 = query_(l, r, (a + b) >> 1, b, u * 2 + 1);
		refresh(u);
		return max(v1, v2);
	}
	long long query(int l, int r) {
		return query_(l, r, 0, size_, 1);
	}
};

// Input
long long N, A[1 << 18], B[1 << 18], C[1 << 18];
long long Q, D[1 << 18], E[1 << 18];
long long W;
vector<pair<int, long long>> X[1 << 18];

// Some Information
long long dist[1 << 18];

// Subtask 2
void dfs1(int pos, long long dep) {
	dist[pos] = dep;
	for (int i = 0; i < X[pos].size(); i++) {
		if (dist[X[pos][i].first] != (1LL << 60)) continue;
		dfs1(X[pos][i].first, dep + X[pos][i].second);
	}
}

void getdist(int pos) {
	for (int i = 1; i <= N; i++) dist[i] = (1LL << 60);
	dfs1(pos, 0);
}

long long solve1() {
	for (int i = 1; i <= N; i++) X[i].clear();
	for (int i = 1; i <= N - 1; i++) {
		X[A[i]].push_back(make_pair(B[i], C[i]));
		X[B[i]].push_back(make_pair(A[i], C[i]));
	}
	getdist(1);
	pair<long long, int> maxn1 = make_pair(-1, -1);
	for (int i = 1; i <= N; i++) maxn1 = max(maxn1, make_pair(dist[i], i));
	getdist(maxn1.second);
	pair<long long, int> maxn2 = make_pair(-1, -1);
	for (int i = 1; i <= N; i++) maxn2 = max(maxn2, make_pair(dist[i], i));
	return maxn2.first;
}

void solve_subtask2() {
	long long last = 0;
	for (int i = 1; i <= Q; i++) {
		D[i] = (D[i] + last) % (N - 1LL) + 1LL;
		E[i] = (E[i] + last) % W;
		C[D[i]] = E[i];
		last = solve1();
		printf("%lld\n", last);
	}
}

int cnts, cl[1 << 18], cr[1 << 18], depth[1 << 18], idx[1 << 18];
vector<int> Y[1 << 18];
LazySegmentTree Z;
set<pair<long long, int>> Set;

void dfs2(int pos, int dep) {
	depth[pos] = dep;
	cnts++; cl[pos] = cnts;
	for (int i = 0; i < X[pos].size(); i++) {
		if (cl[X[pos][i].first] >= 1) continue;
		Y[pos].push_back(X[pos][i].first);
		dfs2(X[pos][i].first, dep + 1);
	}
	cr[pos] = cnts;
}

void dfs3(int pos, int id) {
	idx[pos] = id;
	for (int i : Y[pos]) dfs3(i, id);
}

void solve_subtask5() {
	dfs2(1, 0);
	for (int i = 0; i < Y[1].size(); i++) dfs3(Y[1][i], Y[1][i]);

	Z.init(N + 2);
	for (int i = 1; i <= N - 1; i++) {
		if (depth[A[i]] > depth[B[i]]) swap(A[i], B[i]);
		Z.add(cl[B[i]], cr[B[i]] + 1, C[i]);
	}
	for (int i = 0; i < Y[1].size(); i++) {
		long long val = Z.query(cl[Y[1][i]], cr[Y[1][i]] + 1);
		Set.insert(make_pair(val, Y[1][i]));
	}

	long long last = 0;
	for (int i = 1; i <= Q; i++) {
		D[i] = (D[i] + last) % (N - 1LL) + 1LL;
		E[i] = (E[i] + last) % W;
		long long changes = E[i] - C[D[i]];
		long long pos = B[D[i]];
		long long root = idx[B[D[i]]];
		long long val1 = Z.query(cl[root], cr[root] + 1);
		Set.erase(make_pair(val1, root));
		Z.add(cl[pos], cr[pos] + 1, changes);
		long long val2 = Z.query(cl[root], cr[root] + 1);
		Set.insert(make_pair(val2, root));

		long long r = 0; auto itr = Set.end();
		for (int t = 1; t <= 2; t++) {
			if (itr == Set.begin()) break;
			itr--;
			r += (*itr).first;
		}
		last = r; C[D[i]] = E[i];
		printf("%lld\n", r);
	}
}

long long maxdist[1 << 18];
long long val[1 << 18];
priority_queue<pair<long long, int>, vector<pair<long long, int>>, less<pair<long long, int>>> Que;

void solve_subtask4() {
	for (int i = 1; i <= N - 1; i++) val[B[i]] = C[i];
	for (int i = N / 2; i >= 1; i--) maxdist[i] = max(maxdist[i * 2] + val[i * 2], maxdist[i * 2 + 1] + val[i * 2 + 1]);
	for (int i = 1; i <= N / 2; i++) Que.push(make_pair(maxdist[i * 2] + val[i * 2] + maxdist[i * 2 + 1] + val[i * 2 + 1], i));

	long long last = 0;
	for (int i = 1; i <= Q; i++) {
		D[i] = (D[i] + last) % (N - 1LL) + 1LL;
		E[i] = (E[i] + last) % W;

		int pos = B[D[i]]; val[pos] = E[i];
		while (pos >= 2) {
			pos >>= 1;
			maxdist[pos] = max(maxdist[pos * 2] + val[pos * 2], maxdist[pos * 2 + 1] + val[pos * 2 + 1]);
			Que.push(make_pair(maxdist[pos * 2] + val[pos * 2] + maxdist[pos * 2 + 1] + val[pos * 2 + 1], pos));
		}
		while (!Que.empty()) {
			pair<long long, int> R = Que.top();
			if (maxdist[R.second * 2] + val[R.second * 2] + maxdist[R.second * 2 + 1] + val[R.second * 2 + 1] != R.first) Que.pop();
			else break;
		}

		last = Que.top().first;
		printf("%lld\n", last);
	}
}

int main() {
	scanf("%lld%lld%lld", &N, &Q, &W); bool flag = false;
	for (int i = 1; i <= N - 1; i++) {
		scanf("%lld%lld%lld", &A[i], &B[i], &C[i]); if (A[i] > B[i]) swap(A[i], B[i]);
		if (B[i] - 2LL * A[i] < 0 || 1 < B[i] - 2LL * A[i]) flag = true;
		X[A[i]].push_back(make_pair(B[i], C[i])); 
		X[B[i]].push_back(make_pair(A[i], C[i])); 
	}
	for (int i = 1; i <= Q; i++) scanf("%lld%lld", &D[i], &E[i]);

	if (N <= 5000 && Q <= 5000) {
		solve_subtask2();
	}
	else if (flag == false) {
		solve_subtask4();
	}
	else {
		solve_subtask5();
	}
	return 0;
}

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

diameter.cpp:9:0: warning: ignoring #pragma warning  [-Wunknown-pragmas]
 #pragma warning (disable: 4996)
 
diameter.cpp: In function 'void dfs1(int, long long int)':
diameter.cpp:70:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < X[pos].size(); i++) {
                  ~~^~~~~~~~~~~~~~~
diameter.cpp: In function 'void dfs2(int, int)':
diameter.cpp:115:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < X[pos].size(); i++) {
                  ~~^~~~~~~~~~~~~~~
diameter.cpp: In function 'void solve_subtask5()':
diameter.cpp:130:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < Y[1].size(); i++) dfs3(Y[1][i], Y[1][i]);
                  ~~^~~~~~~~~~~~~
diameter.cpp:137:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < Y[1].size(); i++) {
                  ~~^~~~~~~~~~~~~
diameter.cpp: In function 'int main()':
diameter.cpp:198:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%lld%lld%lld", &N, &Q, &W); bool flag = false;
  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:200:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%lld%lld%lld", &A[i], &B[i], &C[i]); if (A[i] > B[i]) swap(A[i], B[i]);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:205:36: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for (int i = 1; i <= Q; i++) scanf("%lld%lld", &D[i], &E[i]);
                               ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
#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...