番号を所有している各ノードとビットセットのメンテナンス。
#include <ビット/ STDC ++。H> の#defineは LL長い長 の#define LD長い二 の#define ULL符号なし長い長 の#define第Fiの に#define SE第二 の#define MK make_pair の#define PLL対<LL、LL> の#define PLI対<LL、整数> の#define PII対<整数、整数> の#define SZ(X)((INT)x.size()) の#define ALL(X)(X).begin()、(X).END( ) の#define FIOイオス:: sync_with_stdio(偽); cin.tie(0)。使用して名前空間はstdを、CONSTのINT N = 1E5 + 7 。 const int型 INF = 0x3f3f3f3f 。 constの LL INF = 0x3f3f3f3f3f3f3f3f 。 const int型 MOD = 1E9 + 7 。 constの ダブル EPS = 1E- 8 ; CONST ダブル PI = ACOS( - 1 )。 テンプレート < クラス T、クラス S>インラインボイド追加(T&、S b)は{A + B =。もし(A> = MOD)A - = MOD;} テンプレート < クラス T、クラス S>インラインボイドサブ(T&、S b)は、{ - = B。もし(< 0)、A + = MOD;} テンプレート < クラス T、クラス S>インラインブール chkmax(T&、S b)は{ 返す <bは?= B、真:偽;} テンプレート < クラス T、クラス S>インラインブール chkmin(T&、S b)は{ 返す > bは?= B、真:偽;} int型N、M、Q、[N]。 INT における[N]、OT [N]、B [N]、IDX。 ビット集合 < 1000年 > TMP [ 2 ]。 ビットセット < 1000年> プライム; ビットセット < 1000年 > ANS; ベクター < INT > G [N]。 #define LSONリットル、ミッド、室温<< 1つ の#define半ば+ 1、R、RT << 1 rson | 1 構造体setmentTree { ビットセット < 1000年 > [N << 2 ]。 INT怠惰[N << 2 ]。 インラインボイドガオ(int型 RT、int型のC){ TMP [ 0 ] =([RT] <<(1000 - M))>>(1000 - C)。 TMP [1 ] =([RT] <<(C + 1000年 - M))>>(1000年 - M)。 [RT] = tmpに[ 0 ] | TMP [ 1 ]。 怠惰[RT] + = C。もし(怠惰[RT]> = M)怠惰[RT] - = M。 } インラインボイドプッシュ(INT RT){ 場合(怠惰[RT]){ ガオ(RT << 1 、怠惰[RT])。 ガオ(RT << 1 | 1 、怠惰[RT]); 怠惰[RT] = 0 ; } } ボイドビルド(int型 * Bを、int型の L、INT R、INT RT){ 場合(L == R){ [RT] [B [L] = 1 。 返します。 } INT半ば= L + R >> 1 。 (B、LSON)を構築します。(B、rson)を構築します。 [RT] [RT << = 1 ] | [RT << 1 | 1 ]。 } ボイド更新(int型 L、INT R、int型のVal、INT L、INT R、INT RT){ 場合(R <L || R <L || R <L)のリターン; もし(L <= 1 && R <= R){ ガオ(RT、ヴァル)。 返します。 } プッシュ(RT)。 INT半ば= L + R >> 1 。 アップデート(L、R、ヴァル、LSON)。 アップデート(L、R、ヴァル、rson)。 [RT] [RT << = 1 ] | [RT << 1 | 1 ]。 } ビットセット < 1000 >クエリ(INT L、INT R、INTL、INT R、INT RT){ 場合(L <= 1 && R <= R)を返す[RT]を。 プッシュ(RT)。 INT半ば= L + R >> 1 。 ビットセット < 1000年 > ANS; もし(L <=半ば)ANS | = クエリ(L、R、LSON)。 もし(R>中旬)ANS | = クエリ(L、R、rson)。 戻るANSを。 } }木。 ボイド DFS(INT U、INT FA){ で [U] = ++ IDX。 B [IDX] = [U]。 用(オート&:V G [U]) であれば(!V = FA)DFS(V、U); OT [U] = IDX。 } BOOL isPrime(INT X){ ため(int型 I = 2 ; iは= xを<*; iは++ ) 場合(私は==のx%0)を返す 偽。 返す 真; } int型のmain(){ scanf関数(" %D%D%"、&N、&M)。 以下のために(int型 I = 2 ; iがmを<; iは++)プライム[I] =isPrime(I); 用(int型 I = 1のscanf(; iが<= N I ++)は、 " %のD "、および[I])、[I]%= M。 以下のために(int型 i = 1 ; iがn <; iは++ ){ int型Uを、V。 scanf関数(" %d個の%d個"、&U&V); G [U] .push_back(V)。 G [V] .push_back(U)。 } DFS(1、0 ); Tree.build(B、1、nは、1 )。 scanf関数(" %d個"、&Q)。 一方、(q-- ){ int型のOP、V、X。 scanf関数(" %のD "、&OP)。 もし(OPの== 1 ){ scanf関数(" %d個の%のD "、&V、およびX)。 X%= M。 Tree.update(で [V]、[V]、XさOT 1、nは、1 )。 } 他{ scanf関数(" %のD "、&V)。 ANS = Tree.query(で [V]、[V]とさOT 1、nは、1 )。 printf(" %d個の\ n "、(ANS&プライム).count())。 } } 戻り 0 。 } / * * /