CF633G Yash And Trees

简单题。

先把树拍扁成序列,在 dfn 序上区间修改区间查询。

由于时限 4s,我们可以整点怪的,比如 bitset

把区间内的数有/没有表示成 \(01\) 序列,考虑到区间加取模相当于区间内的数全部循环右移,用 bitset 可以做到 \(O(\frac m \omega)\)

然后用线段树维护这个序列就行了,查询的时候和质数的 bitset 与一下,复杂度 \(O\left(\dfrac{nm\log n}{\omega}\right)\)。跑得飞快。

#include <bits/stdc++.h>
using namespace std;

namespace vbzIO {
	char ibuf[(1 << 20) + 1], *iS, *iT;
	#if ONLINE_JUDGE
	#define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
	#else
	#define gh() getchar()
	#endif
	#define rd read
	#define wr write
	#define pc putchar
	#define pi pair<int, int>
	#define mp make_pair
	#define fi first
	#define se second
	#define pb push_back
	#define ins insert
	#define era erase
	inline int read () {
		char ch = gh();
		int x = 0;
		bool t = 0;
		while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
		while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
		return t ? ~(x - 1) : x;
	}
	inline void write(int x) {
		if (x < 0) {
			x = ~(x - 1);
			putchar('-');
		}
		if (x > 9)
			write(x / 10);
		putchar(x % 10 + '0');
	}
}
using vbzIO::read;
using vbzIO::write;

const int N = 1e5 + 100;
const int M = 1e3 + 100;
int n, m, q, dfc, tot, pr[M], a[N], id[N], p[N], sz[N], tg[N << 2];
vector<int> g[N];
bitset<M> tr[N << 2], vis, S;

void dfs(int u, int fa) {
	p[id[u] = ++dfc] = u, sz[u] = 1;
	for (int v : g[u]) {
		if (v == fa) continue;
		dfs(v, u), sz[u] += sz[v];
	}
}

#define ls x << 1
#define rs x << 1 | 1
#define mid ((l + r) >> 1)
void pushup(int x) { tr[x] = tr[ls] | tr[rs]; }
void pushtg(int x, int c) {
	c %= m, tg[x] = (tg[x] + c) % m;
	tr[x] = (tr[x] >> (m - c)) | ((tr[x] << c) & S);
}

void pushdown(int x) {
	if (!tg[x]) return;
	pushtg(ls, tg[x]), pushtg(rs, tg[x]);
	tg[x] = 0;
}

void build(int l, int r, int x) {
	if (l == r) return tr[x][a[p[l]]] = 1, void();
	build(l, mid, ls), build(mid + 1, r, rs), pushup(x);
}

void add(int l, int r, int s, int t, int c, int x) {
	if (s <= l && r <= t) return pushtg(x, c);
	pushdown(x);
	if (s <= mid) add(l, mid, s, t, c, ls);
	if (t > mid) add(mid + 1, r, s, t, c, rs);
	pushup(x);
}

auto qry(int l, int r, int s, int t, int x) {
	if (s <= l && r <= t) return tr[x];
	pushdown(x);
	if (s > mid) return qry(mid + 1, r, s, t, rs);
	else if (t <= mid) return qry(l, mid, s, t, ls);
	else return qry(l, mid, s, t, ls) | qry(mid + 1, r, s, t, rs);
}

int main() {
	n = rd(), m = rd();
	for (int i = 1; i <= n; i++) a[i] = rd() % m;
	for (int i = 1, u, v; i <= n - 1; i++) {
		u = rd(), v = rd();
		g[u].pb(v), g[v].pb(u);
	}
	dfs(1, 0), build(1, n, 1);
	vis.set(), vis[1] = vis[0] = 0;
	for (int i = 2; i <= m; i++) {
		if (vis[i]) pr[++tot] = i;
		for (int j = 1; j <= tot && i * pr[j] <= m; j++) {
			vis[i * pr[j]] = 0;
			if (i % pr[j] == 0) break;
		}
	}
	for (int i = 0; i <= m - 1; i++) S[i] = 1;
	q = rd();
	while (q--) {
		int op = rd(), u = rd();
		if (op == 1) {
			int v = rd();
			add(1, n, id[u], id[u] + sz[u] - 1, v % m, 1);
		} else wr((qry(1, n, id[u], id[u] + sz[u] - 1, 1) & vis).count()), puts("");
	}
	
	return 0;
}

posted @ 2023-07-20 18:35  Ender_32k  阅读(5)  评论(0编辑  收藏  举报