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. C语言通过匿名管道实现反弹式CMDShell

    #pragma comment(lib,"ws2_32.lib") #ifdef _MSC_VER #pragma comment( linker, "/subsyste ...

  2. zookeeper单机版安装

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

  3. Java调用HTTPS接口的证书配置

    首先需要获取到证书文件. 然后,将证书导入到本地: keytool -import -noprompt -trustcacerts -alias <AliasName> -file < ...

  4. tcpdump命令抓包参数

    在 Linux 命令行中使用 tcpdump 抓包 通过实例学习tcpdump命令 聊聊 tcpdump 与 Wireshark 抓包分析 tcpdump常用参数 -n 显示IP地址和端口号 -v 显 ...

  5. 读取excel合并单元格内容

    def get_excel_content(excel_path): contents = [] if self.log_path.endswith('xls'): workbook = xlrd.o ...

  6. Python-doc rst文件打开

    Python rst文件打开 RST与Python类似Javadoc与Java. 如果下载了别人的Python源码,里面有rst文件夹,我们可以转为html后用浏览器打开 某个开源项目的index.r ...

  7. Win7删除网络位置那些不用的网络位置(驱动器)

    1.初始状态: 映射成功的网络位置如下图 2.要删除这个网络位置:点击"打开网络和共享中心",然后如下图设置: 3.重启电脑之后,删除的"网络位置"不会在资源管 ...

  8. (转)Cognos的下载地址分享

    原文:https://blog.csdn.net/Wikey_Zhang/article/details/76138965 刚开始接触Cognos,发现Cognos真是一款挺不错的报表工具,先分享一下 ...

  9. / | \ # $ ^ & *这些符号怎么读

    供参考: /: slash或forward slash 英 [slæʃ] |: vertical bar或pipe #: number sign或pound sign \: backslash 英 [ ...

  10. Spring Boot 数据访问集成 MyBatis 与事物配置

    对于软件系统而言,持久化数据到数据库是至关重要的一部分.在 Java 领域,有很多的实现了数据持久化层的工具和框架(ORM).ORM 框架的本质是简化编程中操作数据库的繁琐性,比如可以根据对象生成 S ...