CF633G Yash And Trees

dfs 序把树拍成区间,转化为区间问题。

建线段树,维护区间 bitset 表示一个取模后的数是否在区间内出现过。

答案即为区间的 bitset &\& 质数集的 bitset 得到的 bitset11 的个数。

时间复杂度 O(nmlognω)\mathcal O(\frac{nm\log n}{\omega})

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

inline ll read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-')
			f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		x = x * 10ll + c - '0', c = getchar();
	return x * f;
}

const int _ = 1e5 + 10;

int n, m, q, a[_];

bitset<1005> full, tr[_ << 2], ans, pr;

int lz[_ << 2];

int id[_], dfn[_], ed[_], cnt;

vector<int> d[_];

void dfs(int u, int fa)
{
	id[++cnt] = u, dfn[u] = cnt;
	for(int v : d[u]) if(v != fa) dfs(v, u);
	ed[u] = cnt;
}

void pushup(int o)
{
	tr[o] = tr[o << 1] | tr[o << 1 | 1];
}

void tag(int o, int v)
{
	lz[o] += v;
	if(lz[o] >= m) lz[o] -= m;
	tr[o] = ((tr[o] << v) & full) | (tr[o] >> (m - v));
}

void pushdown(int o)
{
	if(lz[o])
		tag(o << 1, lz[o]), tag(o << 1 | 1, lz[o]), lz[o] = 0;
}

void build(int o, int l, int r)
{
	if(l == r)
	{
		tr[o].reset();
		tr[o].set(a[id[l]]);
		return;
	}
	int mid = (l + r) >> 1;
	build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
	pushup(o);
}

void update(int o, int l, int r, int L, int R, int v)
{
	if(r < L || l > R) return;
	if(L <= l && r <= R) return tag(o, v), void();
	pushdown(o);
	int mid = (l + r) >> 1;
	if(L <= mid)
		update(o << 1, l, mid, L, R, v);
	if(R > mid)
		update(o << 1 | 1, mid + 1, r, L, R, v);
	pushup(o);
}

void query(int o, int l, int r, int L, int R)
{
	if(r < L || l > R) return;
	if(L <= l && r <= R) return ans |= tr[o], void();
	pushdown(o);
	int mid = (l + r) >> 1;
	if(L <= mid) query(o << 1, l, mid, L, R);
	if(R > mid) query(o << 1 | 1, mid + 1, r, L, R);
	pushup(o);
}

signed main()
{
	n = read(), m = read();
	for(int i = 0; i < m; ++i) full.set(i);
	for(int i = 1; i <= n; ++i) a[i] = read() % m;
	for(int i = 1, u, v; i < n; ++i)
	{
		u = read(), v = read();
		d[u].push_back(v);
		d[v].push_back(u);
	}
	q = read();
	dfs(1, 0);
	build(1, 1, n);
	for(int i = 2; i < m; ++i) pr.set(i);
	for(int i = 2; i < m; ++i)
		if(pr[i])
			for(int j = i * 2; j <= m; j += i)
				pr.reset(j);
	int op, x, y;
	while(q--)
	{
		op = read();
		if(op == 1)
		{
			x = read(), y = read() % m;
			update(1, 1, n, dfn[x], ed[x], y);
		}
		else
		{
			x = read();
			ans.reset();
			query(1, 1, n, dfn[x], ed[x]);
			cout << (ans & pr).count() << "\n";
		}
	}
	return 0;
}
posted @ 2022-12-01 09:17  蒟蒻orz  阅读(7)  评论(0)    收藏  举报  来源