Submission #619073

#TimeUsernameProblemLanguageResultExecution timeMemory
619073MetalPowerDynamic Diameter (CEOI19_diameter)C++14
100 / 100
4887 ms127876 KiB
#include <bits/stdc++.h>
using namespace std;

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

const int MX = 1e5 + 10;
const int LG = 17;
const ll INF = 1e18 + 7;

int N, Q; ll W;
vector<int> adj[MX];
vector<pair<pli, ll>> edges;

int sz[MX], dead[MX];

void dfs(int u, int v){
	sz[u] = 1;
	for(int nx : adj[u]){
		if(nx == v || dead[nx]) continue;
		dfs(nx, u);
		sz[u] += sz[nx];
	}
}

int cent = -1, ccsize = 0;

void dfc(int u, int v){
	for(int nx : adj[u]){
		if(nx == v || dead[nx]) continue;
		dfc(nx, u);
	}
	if(cent == -1 && sz[u] >= (ccsize + 1) / 2) cent = u;
}

int layer = 0, tim[LG], in[MX][LG], fn[MX][LG], root[MX][LG], par[MX][LG], lnum[MX];

// Centroid Decomposition Layer
	// Euler Tour (in, out) for each layer
	// Root (Centroid) for each layer
	// Parent (if Centroid is root) for each layer

void init(int u, int v){
	root[u][layer] = cent;
	par[u][layer] = v;
	in[u][layer] = ++tim[layer];
	for(int nx : adj[u]){
		if(nx == v || dead[nx]) continue;
		init(nx, u); 
	}
	fn[u][layer] = tim[layer];
}

#define psi pair<int, int>

vector<psi> adt[MX];

void findCentroid(int u){
	
	dfs(u, 0);
	ccsize = sz[u], cent = -1;
	dfc(u, 0);

	// cout << "Centroid is " << cent << '\n';

	{
		init(cent, 0); lnum[cent] = layer;
		for(int nx : adj[cent])
			if(!dead[nx]) adt[cent].push_back({in[nx][layer], nx});
		sort(adt[cent].begin(), adt[cent].end());
	}

	{
		dead[cent] = true;
		for(int nx : adj[cent]){
			if(dead[nx]) continue;
			layer++; findCentroid(nx); layer--;
		}
	}
}

struct itseg{

	ll st[MX << 1];

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

	ll que(int l, int r){
		ll res = 0;
		for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){
			if(l & 1) res = max(res, st[l++]);
			if(r & 1) res = max(res, st[--r]);
		}
		return res;
	}
} superseg;

struct segtree{

	ll st[MX << 2], lz[MX << 2];

	void prop(int id, int l, int r){
		if(lz[id] == 0) return;
		st[id] += lz[id];
		if(l != r){
			lz[id << 1] += lz[id];
			lz[id << 1|1] += lz[id];
		}
		lz[id] = 0;
	}

	void upd(int id, int l, int r, int from, int to, ll v){
		prop(id, l, r);
		if(r < from || l > to) return;
		if(from <= l && r <= to){
			lz[id] += v;
			prop(id, l, r);
		}else{
			int mid = l + r >> 1;
			upd(id << 1, l, mid, from, to, v);
			upd(id << 1|1, mid + 1, r, from, to, v);
			st[id] = max(st[id << 1], st[id << 1|1]);
		}
	}

	ll query(int id, int l, int r, int from, int to){
		prop(id, l, r);
		if(r < from || l > to) return -INF;
		if(from <= l && r <= to){
			return st[id];
		}else{
			int mid = l + r >> 1;
			return max(
				query(id << 1, l, mid, from, to),
				query(id << 1|1, mid + 1, r, from, to)
			);
		}
	}

} seg[LG];

set<pli> dep[MX];
// vector<int> adt[MX];

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

	cin >> N >> Q >> W;
	for(int i = 1; i < N; i++){
		int u, v; ll w; cin >> u >> v >> w;
		adj[u].push_back(v);
		adj[v].push_back(u);
		edges.push_back({{u, v}, w});
	}

	// cout << "find Centroid" << '\n';
	findCentroid(1);

	for(auto x : edges){
		int u = x.fi.fi, v = x.fi.se; 
		ll w = x.se;
		for(int j = 0; j < LG; j++){
			if(root[u][j] != root[v][j]) break;
			if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], w);
			else seg[j].upd(1, 1, N, in[u][j], fn[u][j], w);
		}
	}

	for(int i = 1; i <= N; i++){

		int lyr = lnum[i];
		for(psi& nx : adt[i]) dep[i].insert({seg[lyr].query(1, 1, N, in[nx.se][lyr], fn[nx.se][lyr]), in[nx.se][lyr]});

		{
			ll ans = 0;
			set<pli>::iterator it = dep[i].end(); 

			if(it != dep[i].begin()){
				it--;
				ans += (*it).fi;
			}

			if(it != dep[i].begin()){
				it--;
				ans += (*it).fi;
			}

			superseg.upd(i, ans);
			// cout << "answer for centroid " << i << " is " << ans << '\n';
		}
	}

	// cout << "update depths" << '\n';

	ll last = 0;
	for(int i = 0; i < Q; i++){

		int idx; ll nw; cin >> idx >> nw;
		idx = (int)((last + idx) % (N - 1));
		nw = (last + nw) % W;

		int u = edges[idx].fi.fi, v = edges[idx].fi.se;
		ll df = nw - edges[idx].se;

		// cout << "update edge " << u << " " << v << '\n';

		for(int j = 0; j < LG; j++){

			if(root[u][j] != root[v][j]) break;

			int rt = root[u][j], pnd = -1;
			// cout << "at layer " << j << " " << root[u][j] << '\n';

			if(in[u][j] > in[v][j]){
				int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[u][j] + 1, -1)) - adt[rt].begin();
				pnd = adt[rt][uid - 1].se;
			}else{
				int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[v][j] + 1, -1)) - adt[rt].begin();
				pnd = adt[rt][uid - 1].se;
			}

			dep[rt].erase(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j]));
			if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], df);
			else seg[j].upd(1, 1, N, in[u][j], fn[u][j], df);
			dep[rt].insert(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j]));

			{
				ll ans = 0;
				set<pli>::iterator it = dep[rt].end(); 

				if(it != dep[rt].begin()){
					it--;
					ans += (*it).fi;
				}

				if(it != dep[rt].begin()){
					it--;
					ans += (*it).fi;
				}

				superseg.upd(rt, ans);
			}
		}

		edges[idx].se = nw;

		last = superseg.que(1, N);
		cout << last << '\n';
	}
}

Compilation message (stderr)

diameter.cpp: In member function 'void segtree::upd(int, int, int, int, int, long long int)':
diameter.cpp:124:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  124 |    int mid = l + r >> 1;
      |              ~~^~~
diameter.cpp: In member function 'long long int segtree::query(int, int, int, int, int)':
diameter.cpp:137:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  137 |    int mid = l + r >> 1;
      |              ~~^~~
#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...