답안 #1049393

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1049393 2024-08-08T17:54:24 Z 0npata Sprinkler (JOI22_sprinkler) C++17
0 / 100
4000 ms 1048576 KB
#include<bits/stdc++.h>
using namespace std;

#define int long long
#define vec vector
#define hmap unordered_map

const int MXN = 200'005;
int N, L;
int H[MXN];

bool is_centr[MXN*3];
vec<int> tree[MXN*3];
int fi = MXN;

struct SegNode {
	int mul = 1;

	SegNode merge(SegNode other) {
		//cerr << mul << ' ' << other.mul << '\n';
		return {(mul * other.mul) % L};
	}
};


// retrieves multiple of range mod L
// point update multiply one value
struct SegTree {
	vec<SegNode> data;
	int n;
	SegTree(int in) {
		n = 1;
		while(n < in) n*=2;
		data = vec<SegNode>(n*2);
	}
	void upd(int i, SegNode val) {
		assert(i<n && i>=0);
		i += n;
		//cerr << "SZ: " << data.size() << ' ' << i <<  '\n';

		data[i] = data[i].merge(val);
		while(i > 1) {
			i /= 2;
			data[i] = data[i*2].merge(data[i*2+1]);
		}
	}

	SegNode query_suffix(int l) {
		assert(l<n && l >= 0);
		return _query_suffix(l, n, 1, 0, n);
	}
	SegNode _query_suffix(int l, int r, int ti, int tl, int tr) {
		if(l >= tr || r <= tl) {
			return {};
		}
		if(l <= tl && r >= tr) {
			return data[ti];
		}
		int tm = (tl + tr)/2;
		return _query_suffix(l, r, ti*2, tl, tm).merge(_query_suffix(l, r, ti*2+1, tm, tr));
	}
};

struct Centroid {
	vec<SegTree> subtree_contrs{};
	hmap<int, int> subtree_inds;
	hmap<int, int> dists;
	int root;
	int size;
	SegTree contr;

	Centroid() : contr(1) {}

	Centroid(int root, int size) : root(root), size(size), contr(size+1) {
		is_centr[root] = true;
		subtree_inds[root] = -1;
		contr.upd(0, {H[root]});
		dists[root] = 0;

		int si = 0;
		for(int i = 0; i<tree[root].size(); i++) {
			int u = tree[root][i];
			if(is_centr[u]) continue;

			subtree_contrs.push_back(SegTree(size+1));
			dfs_init(u, root, 1, si++);
		}
	}

	void dfs_init(int u, int p, int d, int s_i) {
		if(is_centr[u]) return;
		subtree_inds[u] = s_i;
		dists[u] = d;
		for(int v : tree[u]) {
			if(v == p) continue;
			dfs_init(v, u, d+(u<N), s_i);
		}
	}
};

Centroid centroids[MXN*3];
int centroid_pars[MXN*3];
int subtree_sz[MXN*3];

void comp_subtree_sz(int u, int p = -1) {
	if(is_centr[u]) {
		subtree_sz[u] = 0;
		return;
	}
	subtree_sz[u] = 1;
	for(int v : tree[u]) {
		if(v == p) continue;
		comp_subtree_sz(v, u);
		subtree_sz[u] += subtree_sz[v];
	}
}

int find_centroid(int u, int p, int mxsz) {
	for(int v : tree[u]) {
		if(v == p) continue;
		if(subtree_sz[v] > mxsz) return find_centroid(v, u, mxsz);
	}
	return u;
}

void decompose(int u, int p = -1) {
	if(is_centr[u]) return;
	comp_subtree_sz(u);
	int v = find_centroid(u, -1, subtree_sz[u]/2);
	///cerr << "initializing centroid: " << v << '\n';
	centroid_pars[v] = p;
	centroids[v] = Centroid(v, subtree_sz[u]);
	for(int w : tree[v]) {
		decompose(w, v);
	}
}

void make_tree_binary(int u, int p = -1) {
	vec<int> ch{};
	for(int v : tree[u]) {
		if(v == p) continue;
		ch.push_back(v);
	}
	if(ch.size() > 2) {
		int p2 = 1;
		while(p2*2 < ch.size()) p2 *= 2;
		int l = fi;
		int r = fi+1;
		fi += 2;
		tree[r].push_back(u);
		while(ch.size() > p2) {
			tree[r].push_back(ch.back());
			ch.pop_back();
		}
		tree[l] = ch;
		tree[l].push_back(u);
		tree[u] = {l, r};
		if(p != -1) tree[u].push_back(p);
	}
	for(int v : tree[u]) {
		if(v == p) continue;
		make_tree_binary(v, u);
	}
}




int32_t main() {
	cin >> N >> L;
	for(int i = 0; i<N-1; i++) {
		int u, v;
		cin >> u >> v;
		u--;v--;
		tree[u].push_back(v);
		tree[v].push_back(u);
	}
	for(int i = 0; i<N; i++) {
		cin >> H[i];
	}

	make_tree_binary(0);

	decompose(0);


	int Q;
	cin >> Q;
	while(Q--) {
	//cerr << "HERE0" << '\n';
		int t;
		cin >> t;
		if(t == 2) {
		//cerr << "Here1" << '\n';
			int u;
			cin >> u;
			u--;
			int ans = 1;
			int ci = u;
			auto mult_ans = [&](int val) {
				ans *= val;
				ans %= L;
			};
			while(ci != -1) {
				int d = centroids[ci].dists[u];
				mult_ans(centroids[ci].contr.query_suffix(d).mul);

				for(int i = 0; i<centroids[ci].subtree_contrs.size(); i++) {
					if(centroids[ci].subtree_inds[u] != i) {
						mult_ans(centroids[ci].subtree_contrs[i].query_suffix(d).mul);
					}
				}

				ci = centroid_pars[ci];
				//cerr << ci << '\n';
			};
			cout << ans << '\n';
		}
		else {
			//cerr <<"HERE2" << '\n';
			int u, d, w;
			cin >> u >> d >> w;
			u--;
			centroids[u].contr.upd(min(centroids[u].contr.n-1, d), {w});
			int ci = centroid_pars[u];
			while(ci != -1) {
				//cerr << "Cur Centroid: " << ci << '\n';
				auto& c = centroids[ci];
				int contr_d = d - c.dists[u];
				if(contr_d < 0) {
					ci = centroid_pars[ci];
					continue;
				}
				auto& st = c.subtree_contrs[c.subtree_inds[u]];
				contr_d = min(contr_d, st.n-1);
				//cerr << st.n << '\n';
				st.upd(contr_d, {w});

				ci = centroid_pars[ci];
				//cerr << ci << '\n';
			}
		}
	}


}

Compilation message

sprinkler.cpp: In constructor 'Centroid::Centroid(long long int, long long int)':
sprinkler.cpp:81:19: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   81 |   for(int i = 0; i<tree[root].size(); i++) {
      |                  ~^~~~~~~~~~~~~~~~~~
sprinkler.cpp: In function 'void make_tree_binary(long long int, long long int)':
sprinkler.cpp:146:14: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  146 |   while(p2*2 < ch.size()) p2 *= 2;
      |         ~~~~~^~~~~~~~~~~
sprinkler.cpp:151:19: warning: comparison of integer expressions of different signedness: 'std::vector<long long int>::size_type' {aka 'long unsigned int'} and 'long long int' [-Wsign-compare]
  151 |   while(ch.size() > p2) {
      |         ~~~~~~~~~~^~~~
sprinkler.cpp: In function 'int32_t main()':
sprinkler.cpp:208:21: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<SegTree>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  208 |     for(int i = 0; i<centroids[ci].subtree_contrs.size(); i++) {
      |                    ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 35 ms 144208 KB Output is correct
2 Correct 32 ms 144212 KB Output is correct
3 Correct 33 ms 144212 KB Output is correct
4 Correct 36 ms 145744 KB Output is correct
5 Runtime error 515 ms 1048576 KB Execution killed with signal 9
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 35 ms 144204 KB Output is correct
2 Runtime error 369 ms 541264 KB Execution killed with signal 11
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 35 ms 144204 KB Output is correct
2 Runtime error 369 ms 541264 KB Execution killed with signal 11
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 32 ms 144212 KB Output is correct
2 Execution timed out 4074 ms 728428 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 32 ms 144220 KB Output is correct
2 Execution timed out 4067 ms 718052 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 35 ms 144208 KB Output is correct
2 Correct 32 ms 144212 KB Output is correct
3 Correct 33 ms 144212 KB Output is correct
4 Correct 36 ms 145744 KB Output is correct
5 Runtime error 515 ms 1048576 KB Execution killed with signal 9
6 Halted 0 ms 0 KB -