Summer Training day6 codeforces633G 线段树、bitset
来源:互联网 发布:linux线程的优先级控制 编辑:程序博客网 时间:2024/06/05 00:23
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:
- for given node v and integer value x, increase all ai in the subtree of node v by value x
- 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.
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.
For each of the queries of the second type print the number of suitable prime numbers.
8 203 7 9 8 4 11 7 31 21 33 44 54 64 75 842 11 1 12 52 4
311
5 108 7 5 1 01 22 31 52 431 1 01 1 22 2
2
由于m<=1000所以我们可以对于每一段都将该段出现的数字存下来。用什么来存储呢?用一个大小为M的bitset就可以了。
然后区间合并就用bitset的or操作给区间加一个数x就相当于对当前区间的bitset做一个循环左移m位的操作。
我们要询问某个区间有多少个质数,只需要一开始将小于m的质数处理出来,生成一个bitset类型为prime,ans表示查询到区间的bitset
那么最后的答案就是(prime & ans).count()
代码:
#include <iostream>#include <cstdio>#include <bitset>#include <cstring>using namespace std;int n,m;const int MAXN = 2e5+7;int a[MAXN],b[MAXN];int head[MAXN];int cnt;const int M = 1005;struct edge{ int v; int next; int cost; }Es[MAXN<<1]; void init(){ cnt = 0; memset(head,-1,sizeof(head)); }inline void add_edge(int i,int j,int cost){ Es[cnt].v = j; Es[cnt].cost = cost; Es[cnt].next = head[i]; head[i] = cnt++; } struct segtree{bitset<M> val[MAXN<<2];int addmark[MAXN<<2];void pushup(int rt){val[rt] = val[rt*2] | val[rt*2 + 1]; }void left_rotate(int rt,int x){x %= m;val[rt] = (val[rt] << x ) | (val[rt] >> (m - x));}void pushdown(int rt){if(addmark[rt]){addmark[rt*2] += addmark[rt];addmark[rt*2+1] += addmark[rt];left_rotate(rt*2,addmark[rt]);left_rotate(rt*2 + 1,addmark[rt]);addmark[rt] = 0;}}void build(int rt,int l,int r){if(l == r){//val[l].reset();val[rt].set(b[l] % m);//cout<<"rt:"<<rt<<" bit:"<<val[rt]<<endl;return ;}int mid = (l + r) / 2;build(rt*2,l,mid);build(rt*2+1,mid+1,r);pushup(rt);//cout<<"rt:"<<rt<<" bit:"<<val[rt]<<endl;}void update(int rt,int l,int r,int ul,int ur,int addval){if(l > ur || r < ul) return ;if(ul <= l && r <= ur){left_rotate(rt,addval);addmark[rt] = (addmark[rt] + addval) % m;return ;}int mid = (l+r)/2;pushdown(rt);update(rt*2,l,mid,ul,ur,addval);update(rt*2+1,mid+1,r,ul,ur,addval);pushup(rt);}bitset<M> query(int rt,int l,int r,int ul,int ur){if(l > ur || r < ul) return bitset<M>(0);if(ul <= l && r <= ur){return val[rt];}pushdown(rt);int mid = (l+r)/2;bitset<M> a = query(rt*2,l,mid,ul,ur);bitset<M> b = query(rt*2+1,mid+1,r,ul,ur);return a | b;}};int IN[MAXN],OUT[MAXN];int index = 0;int dfs(int x,int fa){IN[x] = ++ index;for(int e = head[x];e != -1;e = Es[e].next){int v = Es[e].v;if(v != fa){dfs(v,x);}}OUT[x] = ++ index;}segtree seg;bitset<M> getprime(int x){bitset<M> bit;bit.reset();for(int i = 2;i < x;i++){int f = 1;for(int j = 2;j*j <= i;j++){if(i % j == 0){f = 0;break;}}if(f){bit.set(i);}}return bit;}int main(){init();scanf("%d%d",&n,&m);bitset<M> prime = getprime(m);for(int i = 1;i <= n;i++){scanf("%d",&a[i]);}for(int i = 1;i < n;i++){int a,b;scanf("%d%d",&a,&b);add_edge(a,b,1);add_edge(b,a,1);}dfs(1,0);for(int i = 1;i <= n;i++){b[IN[i]] = b[OUT[i]] = a[i];}seg.build(1,1,2*n);int q;scanf("%d",&q);for(int i = 0;i < q;i++){int op;scanf("%d",&op);if(op == 1){int v,x;scanf("%d%d",&v,&x);seg.update(1,1,2*n,IN[v],OUT[v],x % m);}else if(op == 2){int v;scanf("%d",&v);bitset<M> bit = seg.query(1,1,2*n,IN[v],OUT[v]);//cout<<"count:"<<bit<<endl;printf("%d\n",(bit & prime).count());}}return 0;}
- Summer Training day6 codeforces633G 线段树、bitset
- Summer Training day6 coseforces339D 线段树、位操作
- Summer Training day6 codeforces240F 线段树、回文串
- Summer Training day6 codeforces343D dfs序、线段树
- bitset+DFS序+线段树 Codeforces633G Yash And Trees
- Summer Training day6 codeforces787D 最短路spfa,线段树建图
- Summer Training day6 codeforces 675D 二叉搜索树
- Summer training day6 codeforces19E 树链剖分,并查集
- Summer Training day6 codeforces 593D LCA+并查集
- Summer Training day6 codeforces292D并查集合并
- 【BNU Summer Training 2014.08.11】 Nested Segments (线段树,离散化)
- 2016 UESTC Training for Data Structures Q - 昊昊爱运动 II 线段树+延迟操作+bitset
- 2016 UESTC Training for Data Structures Q - 昊昊爱运动 II CDOJ 1259 线段树+bitset
- cdoj1259 线段树+bitset
- cdoj 1259 线段树+bitset
- Tri_integral Summer Training 6
- BUPT-SUMMER-TRAINING-搜索
- 2017 Summer Training Day1
- CentOS7防火墙firewalld和iptable的设置和使用
- c#基础 类与结构体的区别 继承
- RocketMQ——Consumer端自动地不间断地发起拉取消息的业务逻辑
- 算法服务平台-10002-关于测试(02)
- 180
- Summer Training day6 codeforces633G 线段树、bitset
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188