G. Yash And Trees

time limit per test:4 seconds
memory limit per test:512 megabytes
input:standard input
output:standard output

Yash loves playing with trees and gets especially excited when they have something to do with prime numbers. On his 20th birthday he was granted with a rooted tree of n nodes to answer queries on. Hearing of prime numbers on trees, Yash gets too intoxicated with excitement and asks you to help out and answer queries on trees for him. Tree is rooted at node 1. Each node i has some value ai associated with it. Also, integer m is given.

There are queries of two types:

  1. for given node v and integer value x, increase all ai in the subtree of node v by value x
  2. for given node v, find the number of prime numbers p less than m, for which there exists a node u in the subtree of v and a non-negative integer value k, such that au = p + m·k.

Input

The first of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 1000) — the number of nodes in the tree and value m from the problem statement, respectively.

The second line consists of n integers ai (0 ≤ ai ≤ 109) — initial values of the nodes.

Then follow n - 1 lines that describe the tree. Each of them contains two integers ui and vi (1 ≤ ui, vi ≤ n) — indices of nodes connected by the i-th edge.

Next line contains a single integer q (1 ≤ q ≤ 100 000) — the number of queries to proceed.

Each of the last q lines is either 1 v x or 2 v (1 ≤ v ≤ n, 0 ≤ x ≤ 109), giving the query of the first or the second type, respectively. It's guaranteed that there will be at least one query of the second type.

Output

For each of the queries of the second type print the number of suitable prime numbers.

Examples

input

8 20
3 7 9 8 4 11 7 3
1 2
1 3
3 4
4 5
4 6
4 7
5 8
4
2 1
1 1 1
2 5
2 4

output

3
1
1

input

5 10
8 7 5 1 0
1 2
2 3
1 5
2 4
3
1 1 0
1 1 2
2 2

output

2

题意:给你一棵树,根节点为1

   有2种操作,第一种是给u节点所在的子树的所有节点的权值+x

   第二种是询问,假设v是子树u中的节点,有多少种质数满足av = p + m·k,其中p<m

思路:首先用DFS序,把树转换为线性问题,使用线段树维护区间

   因为m<=1000,我们用bitset保存av%m的值

   每次对子树增加权值的时候,只需要修改懒惰标记,来记录增加的大小

   然后直接把bitset利用位运算来完成循环移动就行了。

 //2017-09-05
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bitset>
#define lson (id<<1)
#define rson ((id<<1)|1)
#define mid ((tree[id].l+tree[id].r)>>1)
using namespace std; const int N = ;
const int M = ;
int n, m;
int head[N], tot;
struct Edge{
int to, next;
}edge[N<<]; void init(){
tot = ;
memset(head, -, sizeof(head));
} void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} //dfn记录dfs序,in[u]~out[u]的区间表示以u为根的子树。
int in[N], out[N], idx, dfn[N];
void dfs(int u, int fa){
in[u] = ++idx;
dfn[idx] = u;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(v != fa)
dfs(v, u);
}
out[u] = idx;
} int arr[N];
bitset<M> prime;
bool is_prime(int x){
for(int i = ; i*i <= x; i++)
if(x%i == )return false;
return true;
} void init_prime(){
prime.reset();
for(int i = ; i < m; i++)
if(is_prime(i))
prime.set(i);
} struct Node{
int l, r, lazy;
bitset<M> value;//value记录该区间内%m的余数的集合
}tree[N<<]; void push_up(int id){
tree[id].value = tree[lson].value | tree[rson].value;
} //循环移位,即value集合的每个数都加上了x。
void cyclic_shift(int id, int x){
tree[id].value = (tree[id].value<<x) | (tree[id].value>>(m-x));
} void push_down(int id){
if(tree[id].lazy){
tree[lson].lazy += tree[id].lazy;
tree[lson].lazy %= m;
tree[rson].lazy += tree[id].lazy;
tree[rson].lazy %= m;
cyclic_shift(lson, tree[id].lazy);
cyclic_shift(rson, tree[id].lazy);
tree[id].lazy = ;
}
} void build(int id, int l, int r){
tree[id].l = l;
tree[id].r = r;
tree[id].lazy = ;
if(l == r){
tree[id].value.reset();
tree[id].value.set(arr[dfn[l]]%m);
return;
}
build(lson, l, mid);
build(rson, mid+, r);
push_up(id);
} void update(int id, int l, int r, int x){
if(l <= tree[id].l && tree[id].r <= r){
tree[id].lazy += x;
tree[id].lazy %= m;
cyclic_shift(id, x);
return;
}
push_down(id);
if(l <= mid)update(lson, l, r, x);
if(r > mid)update(rson, l, r, x);
push_up(id);
} bitset<M> query(int id, int l, int r){
if(l <= tree[id].l && tree[id].r <= r){
return tree[id].value;
}
push_down(id);
bitset<M> ans;
if(l <= mid) ans |= query(lson, l, r);
if(r > mid)ans |= query(rson, l, r);
return ans;
} int main()
{
//freopen("inputI.txt", "r", stdin);
while(scanf("%d%d", &n, &m) != EOF){
//由于循环移位会将1移除m的范围,所以每次只求[1,m)之间的素数。
init_prime();
for(int i = ; i <= n; i++)
scanf("%d", &arr[i]);
int u, v;
init();
for(int i = ; i < n; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
idx = ;
dfs(, );
build(, , n);
int q, t, x;
scanf("%d", &q);
while(q--){
scanf("%d%d", &t, &v);
if(t == ){
scanf("%d", &x);
update(, in[v], out[v], x%m);
}else if(t == ){
bitset<M> ans = query(, in[v], out[v]);
printf("%d\n", (int)((ans&prime).count()));
}
}
} return ;
}

Codeforces633G(SummerTrainingDay06-I dfs序+线段树+bitset)的更多相关文章

  1. DFS序+线段树+bitset CF 620E New Year Tree(圣诞树)

    题目链接 题意: 一棵以1为根的树,树上每个节点有颜色标记(<=60),有两种操作: 1. 可以把某个节点的子树的节点(包括本身)都改成某种颜色 2. 查询某个节点的子树上(包括本身)有多少个不 ...

  2. Manthan, Codefest 16 G. Yash And Trees dfs序+线段树+bitset

    G. Yash And Trees 题目连接: http://www.codeforces.com/contest/633/problem/G Description Yash loves playi ...

  3. codeforces 620E. New Year Tree dfs序+线段树+bitset

    题目链接 给一棵树, 每个节点有颜色, 两种操作, 一种是将一个节点的子树全都染色成c, 一种是查询一个节点的子树有多少个不同的颜色, c<=60. 每个节点一个bitset维护就可以. #in ...

  4. codeforces 633G. Yash And Trees dfs序+线段树+bitset

    题目链接 G. Yash And Trees time limit per test 4 seconds memory limit per test 512 megabytes input stand ...

  5. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  6. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  7. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  8. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  9. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

随机推荐

  1. adb shell pm list packages的用法

    abd shell pm list packages     ####查看当前连接设备或者虚拟机的所有包 adb shell pm list packages -d    #####只输出禁用的包. ...

  2. 2018宁夏邀请赛网赛 I. Reversion Count(java练习题)

    题目链接 :https://nanti.jisuanke.com/t/26217 Description: There is a positive integer X, X's reversion c ...

  3. Mac下IDE无法读取环境变量问题

    今天遇到一个问题,Idea无法读取~/.bash_profile下的配置文件. 上网查了好久,都说是launchctl的问题. 但是其实我这边是因为安装了zsh,导致环境标量失效. 在~/.zshrc ...

  4. Python小白学习之路(二十六)—【if __name__ =='__main__':】【用状态标识操作】

    规则一: 一个python文件中,只写一些可以运行的功能测试代码写在这句代码下面 if __name__ =='__main__': 在讲这边的时候,我不是很懂参考了一篇博客,地址如下:http:// ...

  5. redis缓存存在的隐患及其解决方案

    redis缓存1.缓存穿透 1>.什么是缓存穿透? 业务系统需要查训的数据根本不存在,当业务系统查询时, 首先会在缓存中查训,由于缓存中不存在,然后在往数据 库中查,由于该数据在数据库中也不存在 ...

  6. centos 安装nginx笔记

    添加nginx 存储库 yum install epel-release 安装 yum install nginx 启动 systemctl start nginx

  7. 使用libcurl的正确姿势

    libcurl支持访问http.ftp等各种服务器,下载图片AV什么的不在话下.但其存在多种接口,异步接口也很难以理解,到底什么样的使用姿势才是正确滴?我们来看看可用的体位: easy interfa ...

  8. spring@Transactional注解事务不回滚不起作用无效的问题处理

    这几天在项目里面发现我使用@Transactional注解事务之后,抛了异常居然不回滚.后来终于找到了原因. 如果你也出现了这种情况,可以从下面开始排查. 一.特性先来了解一下@Transaction ...

  9. 全网最详细的Oracle10g/11g的官方下载地址集合【可直接迅雷下载安装】(图文详解)

    不多说,直接上干货! 方便自己,也方便他人查阅. Oracle 11g的官网下载地址:  http://www.oracle.com/technetwork/database/enterprise-e ...

  10. Java运行时,指定程序文件的编码

    在命令行cmd里面运行 java -jar test.jar的时候,发现里面执行的汉字发生乱码.原来指定的是UTF-8. 解决如下: java -Dfile.encoding=UTF-8 -jar - ...