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#6.0语言规范(六) 转换

    转换能够被视为是一个特定类型的表达式.转换可能会导致给定类型的表达式被视为具有不同的类型,或者它可能导致没有类型的表达式获取类型.转换可以是隐式或显式的,这决定了是否需要显式转换.例如,从类型int到 ...

  2. UICollectionView设置首个cell默认选中(二)

    上篇对于UICollectionView默认选中cell采取的是每个cell分别对应一个标识,也就代表着废除了UICollectionView的重用机制.对于较少的数据情况是可以的,但是对于数据比较大 ...

  3. Nginx安装使用及与tomcat实现负载均衡

    1. 背景 基于nginx强大的功能,实现一种负载均衡,或是不停机更新程序等.nginx相比大家基本上都知道是什么来头了,具体的文章大家可以去搜索相关文章学习阅读,或是可以查看Nginx中文文档和Ng ...

  4. Windows Phone开发手记-WinRT下启动器替代方案

    在WP7/8时代,Silverlight框架提供了很多启动器API,我们可以很方便的使用的,来完成一些系统级的操作.但是随着Win RT架构的WP8.1(SL 8.1除外)的到来,原有的SL下的启动器 ...

  5. C++类和对象(一)&&实现offsetof宏&&this指针

    一.目录 1.对象的相关知识 2.类的定义 3.类的实例化 4.类对象模型 5.模拟实现offsetof宏 6.this指针 二.正文 1.对象的相关知识 C语言是面向过程的,关注的是过程,分析求解问 ...

  6. (转)percona的安装、启动、停止

    原文:https://blog.csdn.net/tanliqing2010/article/details/78758878 socket=/percona/3307/data/mysql.sock ...

  7. iOS Round Double value to 2 decimal digits and round 3rd decimal digit up

    I have I double value like this one 17.125. It should be rounded up to 17.13 If I use the simple met ...

  8. Android_触摸事件传递机制

    Android中dispatchTouchEvent,onInterceptTouchEvent, onTouchEvent的理解ecandroid中的事件类型分为按键事件和屏幕触摸事件,Touch事 ...

  9. 解决org.apache.shiro.session.UnknownSessionException: There is no session with id的问题

    一.背景 最近在整合了Spring+Shiro+Redis实现tomcat集群session共享的问题之后,发布以后运行以后发现老是会出现:org.apache.shiro.session.Unkno ...

  10. JS中this的那些事儿

    this是JavaScript中最复杂的机制之一.它是一个很特别的关键字,被自动定义在所有函数的作用域中. 一.this到底指向什么? this既不指向函数自身,也不指向函数的词法作用域,具体指向什么 ...