CF633G Yash And Trees 题解
简单题。
先看到子树加和子树质数个数和,果断转换为 dfs
序进行处理。
既然有区间求和,考虑线段树。
若对于每一个节点维护一个 x_u = (x_u << v & full) | (x_u >> (m - v))
,其中
都到这一步了,不会还有人不知道怎么优化吧。
既然是二进制的数,用 bitset 进行优化即可。
时间复杂度:
代码:
const int N = 1e5 + 10, M = 1e3 + 10;
int n, m, Q, tot;
int a[N], b[N];
int tag[N << 2], d[N], siz[N], dfn[N], rdfn[N];
bitset<M> tr[N << 2], pr, f, ans;
int head[N], cnte;
struct edge {
int v, nxt;
} e[N << 1];
void adde(int u, int v) {
e[++cnte].nxt = head[u];
e[cnte].v = v;
head[u] = cnte;
}
void pushup(int u) {
tr[u] = tr[u << 1] | tr[u << 1 | 1];
}
void pushdown(int u) {
if (tag[u]) {
tag[u << 1] = (tag[u << 1] + tag[u]) % m, tag[u << 1 | 1] = (tag[u << 1 | 1] + tag[u]) % m;
tr[u << 1] = (tr[u << 1] << tag[u]) | (tr[u << 1] >> (m - tag[u]));
tr[u << 1 | 1] = ((tr[u << 1 | 1] << tag[u]) & f) | (tr[u << 1 | 1] >> (m - tag[u]));
tag[u] = 0;
}
}
void build(int u, int l, int r, int *a) {
if (l == r) {
tr[u].reset();
tr[u].set(a[l]);
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid, a), build(u << 1 | 1, mid + 1, r, a);
pushup(u);
}
void update(int u, int l, int r, int L, int R, int val) {
if (L <= l && r <= R) {
tag[u] = (tag[u] + val) % m;
tr[u] = ((tr[u] << val) & f) | (tr[u] >> (m - val));
return;
}
pushdown(u);
int mid = l + r >> 1;
if (L <= mid) update(u << 1, l, mid, L, R, val);
if (mid < R) update(u << 1 | 1, mid + 1, r, L, R, val);
pushup(u);
}
void query(int u, int l, int r, int L, int R) {
if (L <= l && r <= R) {
ans |= tr[u];
return;
}
pushdown(u);
int mid = l + r >> 1;
if (L <= mid) query(u << 1, l, mid, L, R);
if (mid < R) query(u << 1 | 1, mid + 1, r, L, R);
}
void dfs_init(int u, int f) {
d[u] = d[f] + 1, siz[u] = 1, dfn[u] = ++tot, rdfn[tot] = u;
for (int i = head[u], v; i != 0; i = e[i].nxt)
if ((v = e[i].v) != f) {
dfs_init(v, u);
siz[u] += siz[v];
}
}
int main() {
ios
cin >> n >> m;
for (int i = 0; i < m; i++) f.set(i);
for (int i = 2; i < m; i++) pr.set(i);
for (int i = 2; i < m; i++)
if (pr[i]) {
for (int j = 2 * i; j < m; j += i)
pr.reset(j);
}
for (int i = 1; i <= n; i++) {
cin >> a[i];
a[i] %= m;
}
for (int i = 1, u, v; i < n; i++) {
cin >> u >> v;
adde(u, v), adde(v, u);
}
dfs_init(1, 0);
for (int i = 1; i <= n; i++) b[i] = a[rdfn[i]];
build(1, 1, n, b);
cin >> Q;
while (Q--) {
int opt, u, x;
cin >> opt >> u;
if (opt == 1) {
cin >> x;
update(1, 1, n, dfn[u], dfn[u] + siz[u] - 1, x % m);
} else {
ans.reset();
query(1, 1, n, dfn[u], dfn[u] + siz[u] - 1);
int res = (ans & pr).count();
cout << res << "\n";
}
}
return 0;
}
标签:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端