题目描述
绪萌同人社是一个有趣的组织,该组织结构是一个树形结构。有一个社长,直接下属一些副社长。每个副社长又直接下属一些部长……。
每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素乘积构成(例如,猫耳的值是2,弱气的值是3,黄毛的值是5,病娇的值是7,双马尾的值是11等等)
举个例子,正妹是双份的猫耳,而且有一份弱气,她的属性值为2*2*3=12。
现在组员关心一个问题,希望知道离自己最近且有相同萌元素上司是谁,例如,属性值为2、4、6、45这样的属性值都算是和正妹有相同的属性。
然而,组员可能会随时变化自己的属性。啊。。感觉好麻烦啊。。
输入输出格式
输入格式:
第一行,n,k 表示成员数与询问的次数
第二行,n个数,分别是1~n号成员的属性值
接下来n-1行,x_i,y_i 表示x_i是y_i的上司。
接下来来k行,有两种情况
1 u_i 询问离u_i成员最近且有相同萌元素上司。
2 u_i a 更改u_i的属性值为a
输出格式:
对于每个1类型的询问,输出符合要求的编号。如果没有符合要求的编号,输出-1。
输入输出样例
输入样例:
4 6 10 8 4 3 1 2 2 3 3 4 1 1 1 2
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define inf 0x3f3f3f3f 5 #define M 200200 6 int next[M],pre[M],last[M],n,query,meng[M],tot=0,father[M]; 7 bool vis[M]; 8 int gcd (int a,int b){return b==0?a:gcd(b,a%b);}//1行代码gcd 9 void addedge (int u,int v) 10 { 11 tot++; 12 next[tot]=v;//next数组存的是点 13 pre[tot]=last[u];//pre和last存的是边的编号 14 last[u]=tot; 15 } 16 void dfs (int x) 17 { 18 for (int i=last[x];i;i=pre[i]) 19 father[next[i]]=x,dfs(next[i]);//每个点找上司 20 //因为树是按顺序建的,所以直接无脑搜索就行了,不用vis,因为不可能走重 21 } 22 int main() 23 24 { 25 //freopen("de.txt","r",stdin); 26 scanf("%d%d",&n,&query); 27 memset(vis,false,sizeof vis); 28 for (int i=1;i<=n;++i) 29 scanf("%d",&meng[i]); 30 for (int i=1;i<n;++i) 31 { 32 int x,y; 33 scanf("%d%d",&x,&y); 34 addedge(x,y); 35 } 36 dfs(1); 37 for (int i=0;i<query;++i) 38 { 39 int x,y,z,ans=-1; 40 scanf("%d%d",&x,&y); 41 if (x==2) 42 scanf("%d",&z),meng[y]=z; 43 else 44 { 45 for (int j=father[y];j;j=father[j]) 46 { 47 int a=meng[y],b=meng[j]; 48 if (a>b) swap(a,b); 49 if (gcd(a,b)!=1) 50 { 51 ans=j; 52 break; 53 } 54 } 55 printf("%d\n",ans); 56 } 57 } 58 return 0; 59 }
1 3 1 4 2 1 9 1 4
输出样例:
-1 1 2 -1 1
这道题看评论很水...反正就是练一下树状的结构。顺便学会了1行gcd。
代码如下: