第一次写线段树合并
因为最后只有一次询问,所以树上差分,动态开点权值线段树维护,主要说线段树合并的部分
1 int merge(int x,int y,int l,int r) 2 { 3 if(!x||!y) return x|y; 4 int tmp=x,mid=(l+r)/2; 5 val[tmp]=val[x]+val[y]; 6 son[tmp][0]=merge(son[x][0],son[y][0],l,mid); 7 son[tmp][1]=merge(son[x][1],son[y][1],mid+1,r); 8 if(l==r) maxx[tmp]=val[tmp],pos[tmp]=l; else pushup(tmp); 9 return tmp; 10 }
(Zhang_RQ式线段树合并)
1.有一个节点为空则返回另一个
2.合并信息
3.分别用两个节点的左右儿子和左右区间合并出新节点的左右儿子
4.pushup
注意只有当一个点的最大值不为零时才将答案更新,否则输出零
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005; 6 int son[4*18*N][2],val[4*18*N],maxx[4*18*N],pos[4*18*N]; 7 int num[N],dep[N],anc[N],siz[N],imp[N],top[N],outp[N]; 8 int p[N],noww[2*N],goal[2*N]; 9 int n,m,t1,t2,t3,cnt,tot,c; 10 void link(int f,int t) 11 { 12 noww[++cnt]=p[f]; 13 goal[cnt]=t,p[f]=cnt; 14 } 15 void DFS(int nde,int fth,int dth) 16 { 17 int tmp=0; 18 siz[nde]=1,anc[nde]=fth,dep[nde]=dth; 19 for(int i=p[nde];i;i=noww[i]) 20 if(goal[i]!=fth) 21 { 22 DFS(goal[i],nde,dth+1); 23 siz[nde]+=siz[goal[i]]; 24 if(siz[goal[i]]>tmp) 25 tmp=siz[goal[i]],imp[nde]=goal[i]; 26 } 27 } 28 void MARK(int nde,int tpp) 29 { 30 top[nde]=tpp; 31 if(imp[nde]) 32 { 33 MARK(imp[nde],tpp); 34 for(int i=p[nde];i;i=noww[i]) 35 if(goal[i]!=anc[nde]&&goal[i]!=imp[nde]) 36 MARK(goal[i],goal[i]); 37 } 38 } 39 int LCA(int x,int y) 40 { 41 int tx=top[x],ty=top[y]; 42 while(tx!=ty) 43 { 44 if(dep[tx]<dep[ty]) 45 swap(tx,ty),swap(x,y); 46 x=anc[tx],tx=top[x]; 47 } 48 return dep[x]<dep[y]?x:y; 49 } 50 void pushup(int nde) 51 { 52 int ls=son[nde][0],rs=son[nde][1]; 53 maxx[nde]=max(maxx[ls],maxx[rs]); 54 pos[nde]=(maxx[nde]==maxx[ls])?pos[ls]:pos[rs]; 55 } 56 void create(int &nde,int l,int r,int p,int task) 57 { 58 if(!nde) nde=++c; val[nde]+=task; 59 if(l==r) pos[nde]=l,maxx[nde]=val[nde]; 60 else 61 { 62 int mid=(l+r)/2; 63 if(p<=mid) create(son[nde][0],l,mid,p,task); 64 else create(son[nde][1],mid+1,r,p,task); pushup(nde); 65 } 66 } 67 int merge(int x,int y,int l,int r) 68 { 69 if(!x||!y) return x|y; 70 int tmp=x,mid=(l+r)/2; 71 val[tmp]=val[x]+val[y]; 72 son[tmp][0]=merge(son[x][0],son[y][0],l,mid); 73 son[tmp][1]=merge(son[x][1],son[y][1],mid+1,r); 74 if(l==r) maxx[tmp]=val[tmp],pos[tmp]=l; else pushup(tmp); 75 return tmp; 76 } 77 void ANS(int nde) 78 { 79 for(int i=p[nde];i;i=noww[i]) 80 if(goal[i]!=anc[nde]) 81 ANS(goal[i]),num[nde]=merge(num[nde],num[goal[i]],1,100000); 82 outp[nde]=maxx[num[nde]]?pos[num[nde]]:0; 83 } 84 int main () 85 { 86 scanf("%d%d",&n,&m); 87 for(int i=1;i<n;i++) 88 { 89 scanf("%d%d",&t1,&t2); 90 link(t1,t2),link(t2,t1); 91 } 92 DFS(1,0,1); MARK(1,1); 93 for(int i=1;i<=m;i++) 94 { 95 scanf("%d%d%d",&t1,&t2,&t3); 96 int lca=LCA(t1,t2); 97 create(num[t1],1,100000,t3,1); 98 create(num[t2],1,100000,t3,1); 99 create(num[lca],1,100000,t3,-1); 100 create(num[anc[lca]],1,100000,t3,-1); 101 } 102 ANS(1); 103 for(int i=1;i<=n;i++) 104 printf("%d\n",outp[i]); 105 return 0; 106 }