답안 #1049572

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1049572 2024-08-08T23:35:40 Z 0npata Sprinkler (JOI22_sprinkler) C++17
0 / 100
4000 ms 312920 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];
set<int> tree_i[MXN*3];
int fi = MXN;
bool wn[MXN*3];
hmap<int, int> cache;
int centr_dists[MXN*3][28];
int centr_subtree_inds[MXN*3][28];

const int weight(int u, int v) {
	if(u>v)  swap(u, v);
	if(v < MXN) return 1;
	if(u >= MXN) return 0;
	return wn[v];
}

class FenwickTree {
public:
    int n;
    FenwickTree(int size) : n(size), tree(size + 1, 1) {}

    void upd(int32_t index, int value) {
		index = n-index;
        while (index <= n) {
            tree[index] = (tree[index] * value) % L;
            index += index & -index;
        }
    }

    int query_suffix(int32_t index) {
		index = n-index;
        int result = 1;
        while (index > 0) {
            result = (tree[index] * result) % L;
            index -= index & -index;
        }
        return result;
    }

    std::vector<int> tree;
};

struct Centroid {
	vec<FenwickTree> subtree_contrs{};
	int root;
	int size;
	FenwickTree contr;
	int mxd = 0;
	int layer;

	Centroid() : contr(1) {}

	Centroid(int root, int size, int layer) : root(root), size(size), contr(size+1), layer(layer) {
		is_centr[root] = true;
		centr_subtree_inds[root][layer] = -1;
		if(root < N) contr.upd(0, {H[root]});
		centr_dists[root][layer] = 0;

		int si = 0;
		for(int u : tree[root]) {
			if(is_centr[u]) continue;

			dfs_init(u, root, weight(u, root), si++);
		}

		for(int i = 0; i<si; i++) {
			subtree_contrs.push_back(FenwickTree(mxd+1));
		}
	}

	void dfs_init(int u, int p, int d, int s_i) {
		if(is_centr[u]) return;
		centr_subtree_inds[u][layer] = s_i;
		centr_dists[u][layer] = d;
		mxd = max(mxd, d);
		for(int v : tree[u]) {
			if(v == p) continue;
			dfs_init(v, u, d+weight(v, u), 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, int layer=0) {
	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], layer);
	for(int w : tree[v]) {
		decompose(w, v, layer+1);
	}
}

void make_tree_binary(int u, int p = -1) {
	vec<int> ch{};
	for(int v : tree_i[u]) {
		if(v==p) continue;
		ch.push_back(v);
	}
	if(ch.size() > 4) {
		int p2 = 1;
		while(p2 < ch.size()) {
			p2 *= 2;
		}
		int root = fi;
		tree_i[u].insert(root);
		tree_i[root].insert(u);
		for(int i = 2; i<p2; i++) {
			tree_i[i/2+fi-1].insert(i+fi-1);
			tree_i[i+fi-1].insert(i/2+fi-1);
		}
		for(int i = p2; i<p2+ch.size(); i++) {
			tree_i[i/2+fi-1].insert(ch[i-p2]);
			tree_i[ch[i-p2]].insert(i/2+fi-1);
			wn[i/2+fi-1] = 1;
			tree_i[ch[i-p2]].erase(u);
			tree_i[u].erase(ch[i-p2]);
		}
		fi += p2-1;
	}
	for(int v : tree[u]) {
		if(v == p) continue;
		make_tree_binary(v, u);
	}
}



int32_t main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

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

	auto start = chrono::high_resolution_clock::now();
	make_tree_binary(0);
	if(false) {
	for(int i = 0; i<MXN*3; i++) {
		if(tree[i].size() > 0) {
			cerr << i << ":" << ' ';
			for(int v : tree[i]) cerr << v << ' ';
			cerr << '\n';
		}
	}
	}
	for(int i = 0; i<MXN*3; i++) {
		tree[i] = vec<int>(tree_i[i].begin(), tree_i[i].end());
	}
	auto stop = chrono::high_resolution_clock::now();
	auto duration = chrono::duration_cast<chrono::milliseconds>(stop-start).count();
	cerr << "Binary tree making took: " << duration << " milliseconds" << '\n';


	start = chrono::high_resolution_clock::now();
	decompose(0);

	stop = chrono::high_resolution_clock::now();
	duration = chrono::duration_cast<chrono::milliseconds>(stop-start).count();
	cerr << "Centroid decomposition: " << duration << " milliseconds" << '\n';

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

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

				ci = centroid_pars[ci];
				//cerr << ci << '\n';
			};
			cache[u] = ans;
			cout << ans << '\n';
		}
		else {
			cache = {};
			//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 - centr_dists[u][c.layer];
				if(contr_d < 0) {
					ci = centroid_pars[ci];
					continue;
				}
				auto& st = c.subtree_contrs[centr_subtree_inds[u][c.layer]];
				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 function 'void make_tree_binary(long long int, long long int)':
sprinkler.cpp:139:12: 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]
  139 |   while(p2 < ch.size()) {
      |         ~~~^~~~~~~~~~~
sprinkler.cpp:149:20: warning: comparison of integer expressions of different signedness: 'long long int' and 'long long unsigned int' [-Wsign-compare]
  149 |   for(int i = p2; i<p2+ch.size(); i++) {
      |                   ~^~~~~~~~~~~~~
sprinkler.cpp: In function 'int32_t main()':
sprinkler.cpp:233:21: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<FenwickTree>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  233 |     for(int i = 0; i<centroids[ci].subtree_contrs.size(); i++) {
      |                    ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 119636 KB Output is correct
2 Incorrect 29 ms 121608 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 28 ms 121752 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 28 ms 121752 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 119644 KB Output is correct
2 Correct 1272 ms 312920 KB Output is correct
3 Correct 937 ms 309424 KB Output is correct
4 Correct 1087 ms 310352 KB Output is correct
5 Correct 782 ms 276048 KB Output is correct
6 Correct 715 ms 269016 KB Output is correct
7 Correct 693 ms 266320 KB Output is correct
8 Execution timed out 4043 ms 251312 KB Time limit exceeded
9 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 28 ms 121840 KB Output is correct
2 Incorrect 1255 ms 311764 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 119636 KB Output is correct
2 Incorrect 29 ms 121608 KB Output isn't correct
3 Halted 0 ms 0 KB -