제출 #558465

#제출 시각아이디문제언어결과실행 시간메모리
558465savacskaSprinkler (JOI22_sprinkler)C++17
41 / 100
4091 ms126444 KiB
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef long double ld;

const int MAXD = 40;
const int MAXN = 200000;
int MOD = 0;

vector <int> g[MAXN + 5];
int height[MAXN + 5], position[MAXN + 5], parent[MAXN + 5], start_height[MAXN + 5];
vector <int> rows[MAXN + 5];
pair <int, int> subtree[MAXD + 5][MAXN + 5];
vector <pair <int, int> > tree[MAXN + 5];

int binpow(int x, int step)
{
 	if (step == 0) return 1;
 	if (step % 2 == 0)
 	{
 	 	int t = binpow(x, step / 2);
 	 	return (ll) t * (ll) t % (ll) MOD;
 	}
 	else return (ll) x * (ll) binpow(x, step - 1) % (ll) MOD;
}

void dfs(int v, int pr, int hei)
{
	parent[v] = pr;
	height[v] = hei;
	position[v] = (int) rows[hei].size();
	rows[hei].pb(v);

	int pos = -1;
	for (int i = 0; i < (int) g[v].size(); i++)
		if (g[v][i] == pr) pos = i;
	if (pos != -1)
	{
	 	swap(g[v][pos], g[v].back());
	 	g[v].pop_back();
	}

	for (int u : g[v])
		dfs(u, v, hei + 1);

	subtree[0][v] = mp(position[v], position[v]);
	if (!g[v].empty())
	{
	 	subtree[1][v] = mp(position[g[v][0]], position[g[v].back()]);
	 	int lef = 0, rig = (int) g[v].size() - 1;
	 	for (int i = 2; i <= MAXD; i++)
	 	{
	 	 	while (lef <= rig && subtree[i - 1][g[v][lef]] == mp(-1, -1)) lef++;
	 	 	while (lef <= rig && subtree[i - 1][g[v][rig]] == mp(-1, -1)) rig--;
	 	 	if (lef <= rig) subtree[i][v] = mp(subtree[i - 1][g[v][lef]].x, subtree[i - 1][g[v][rig]].y);
	 	 	else break;
	 	}
	}
	return;
}

void build(vector <pair <int, int> > &tree, int v, int lef, int rig, const vector <int> &num)
{
 	if (lef == rig)
 	{
 		int vv = num[lef];
 		tree[v] = mp(start_height[vv], 1);
 		return; 	
 	}
 	int mid = (lef + rig) / 2;
 	build(tree, 2 * v, lef, mid, num);
 	build(tree, 2 * v + 1, mid + 1, rig, num);
 	tree[v] = mp((ll) tree[2 * v].x * (ll) tree[2 * v + 1].x % (ll) MOD, 1);
 	return;
}

void full(vector <pair <int, int> > &tree, int v, int lef, int rig, int mn)
{
	tree[v].y = (ll) tree[v].y * (ll) mn % (ll) MOD;
	tree[v].x = (ll) tree[v].x * (ll) binpow(mn, rig - lef + 1) % (ll) MOD;
	return;
}

void push(vector <pair <int, int> > &tree, int v, int lef, int rig)
{
 	int mid = (lef + rig) / 2;
 	full(tree, 2 * v, lef, mid, tree[v].y);
 	full(tree, 2 * v + 1, mid + 1, rig, tree[v].y);
 	tree[v].y = 1;
 	return;
}

int get_height(vector <pair <int, int> > &tree, int v, int lef, int rig, int pos)
{
 	if (lef == rig) return tree[v].x;
 	push(tree, v, lef, rig);
 	int mid = (lef + rig) / 2;
 	if (pos <= mid) return get_height(tree, 2 * v, lef, mid, pos);
 	else return get_height(tree, 2 * v + 1, mid + 1, rig, pos);
}

void update(vector <pair <int, int> > &tree, int v, int lef, int rig, int A, int B, int mn)
{
 	if (lef > B || rig < A) return;
 	if (A <= lef && rig <= B)
 	{
 	 	full(tree, v, lef, rig, mn);
 	 	return;
 	}
 	push(tree, v, lef, rig);
 	int mid = (lef + rig) / 2;
 	update(tree, 2 * v, lef, mid, A, B, mn);
 	update(tree, 2 * v + 1, mid + 1, rig, A, B, mn);
 	tree[v].x = (ll) tree[2 * v].x * (ll) tree[2 * v + 1].x % (ll) MOD;
 	return;
}

int main()
{
 	//freopen("input.txt", "r", stdin);
 	//freopen("output.txt", "w", stdout);
 	ios_base::sync_with_stdio(0); cin.tie(0);
 	
 	int n, mod;
 	cin >> n >> mod;
 	MOD = mod;
 	
 	for (int i = 0; i <= MAXD; i++)
 		for (int j = 1; j <= n; j++)
 			subtree[i][j] = mp(-1, -1);

 	for (int i = 1; i < n; i++)
 	{
 	 	int u, v;
 	 	cin >> u >> v;
 	 	g[u].pb(v), g[v].pb(u);
 	}

 	for (int i = 1; i <= n; i++) cin >> start_height[i];

 	dfs(1, -1, 0);
 	
 	{
 	 	int h = 0;
 	 	while (!rows[h].empty())
 	 	{
 	 	 	int sz = (int) rows[h].size();
 	 	 	tree[h].resize(4 * sz, mp(0, 0));
 	 	 	build(tree[h], 1, 0, sz - 1, rows[h]);
 	 		h++;
 	 	}
 	}
 	
 	int quer;
 	cin >> quer;
 	
 	for (int rep = 1; rep <= quer; rep++)
 	{
 	 	int typ;
 	 	cin >> typ;
 	 	if (typ == 1)
 	 	{
 	 	 	int vert, dist, mn;
 	 	 	cin >> vert >> dist >> mn;

 	 	 	vector <int> path;
 	 	 	int tek = vert;
 	 	 	path.pb(tek);
 	 	 	for (int i = 1; i <= dist; i++)
 	 	 	{
 	 	 		if (parent[tek] == -1) break;
 	 	 		tek = parent[tek];
 	 	 		path.pb(tek);
 	 	 	}
 	 	 	for (int fin = height[vert] - dist; fin <= height[vert] + dist; fin++)
 	 	 	{
 	 	 	 	int x = (dist + height[vert] - fin) / 2;
 	 	 	 	if (x >= (int) path.size()) x = (int) path.size() - 1;
 	 	 	 	if (height[path[x]] > fin) continue;

 	 	 	 	int y = fin - height[path[x]];
 	 	 	 	pair <int, int> bounds = subtree[y][path[x]];
 	 	 	 	if (bounds.x == -1) continue;
 	 	 	 	update(tree[fin], 1, 0, (int) rows[fin].size() - 1, bounds.x, bounds.y, mn);
 	 	 	}
 	 	}
 	 	else
 	 	{
 	 		int vert;
 	 		cin >> vert;

 	 		cout << get_height(tree[height[vert]], 1, 0, (int) rows[height[vert]].size() - 1, position[vert]) << '\n';
 	 	}
 	}
 	return 0;
}
#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...