Nowcoder挑战赛39F(模板树上莫队)
Posted chasedeath
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nowcoder挑战赛39F(模板树上莫队)相关的知识,希望对你有一定的参考价值。
Nowcoder挑战赛39F(模板树上莫队)
题意:
给定一棵树,求两点路径上的不同权值个数和权值是k的倍数的个数
分析:
第二问可以直接离线询问,暴力(nsqrt{n})枚举因数更新答案,路径作差
第一问是树上莫队模板题
树上莫队:在 括号序列 上跑莫队,对于单链和双链要分类讨论,更改权值上也有细微差别,还要特判LCA的情况
合理压行和利用C++11有效缩短代码
const int N=1e5+10;
int n,m,len,a[N];
vector <int> G[N],Fac[N];
struct Que{ int x,k,id; };
vector <Que> Q[N];
struct Node{ int l,r,lca,id; } A[N];
int ans[N],dep[N],fa[N][20];
int line[N<<1],L[N],R[N],dfn;
void pre_dfs(int u,int f) {
line[L[u]=++dfn]=u,fa[u][0]=f;
rep(i,1,17) fa[u][i]=fa[fa[u][i-1]][i-1];
for(int v:G[u]) if(v!=f) dep[v]=dep[u]+1,pre_dfs(v,u);
line[R[u]=++dfn]=u;
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=0,del=dep[x]-dep[y];(1<<i)<=del;++i) if(del&(1<<i)) x=fa[x][i];
if(x==y) return x;
drep(i,17,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int vis[N],cnt[N],Now;
void Add(int x){ if((cnt[x]++)==0) Now++; }
void Del(int x){ if((--cnt[x])==0) Now--; }
void Upd(int x){ vis[x]?Del(a[x]):Add(a[x]),vis[x]^=1; }
void dfs(int u,int f) {
for(int t:Fac[a[u]]) cnt[t]++;
for(Que t:Q[u]) ans[t.id]+=cnt[t.x]*t.k;
for(int v:G[u]) if(v!=f) dfs(v,u);
for(int t:Fac[a[u]]) cnt[t]--;
}
int main(){
rep(i,1,N-1) for(int j=i;j<N;j+=i) Fac[j].pb(i);
rep(kase,1,rd()) {
n=rd();
rep(i,1,n) G[i].clear(),Q[i].clear(),vis[i]=0;
rep(i,1,n) a[i]=rd();
rep(i,2,n) {
int u=rd(),v=rd();
G[u].pb(v),G[v].pb(u);
}
dfn=0,pre_dfs(1,0);
len=sqrt(n*2);
rep(i,1,m=rd()) {
int x=rd(),y=rd(),z=rd(),lca=LCA(x,y);
if(L[x]>L[y]) swap(x,y);
if(lca==x) A[i]=(Node){L[x],L[y],0,i};
else A[i]=(Node){R[x],L[y],lca,i};
Q[x].pb((Que){z,1,i}),Q[y].pb((Que){z,1,i});
Q[lca].pb((Que){z,-1,i}),Q[fa[lca][0]].pb((Que){z,-1,i});
}
rep(i,1,m) ans[i]=0;
dfs(1,0);
sort(A+1,A+m+1,[&](Node x,Node y){ return x.l/len<y.l/len||(x.l/len==y.l/len && x.r<y.r);});
int l=1,r=0;
rep(i,1,m) {
while(l<A[i].l) Upd(line[l++]);
while(l>A[i].l) Upd(line[--l]);
while(r>A[i].r) Upd(line[r--]);
while(r<A[i].r) Upd(line[++r]);
if(A[i].lca) Upd(A[i].lca);
ans[A[i].id]^=Now;
if(A[i].lca) Upd(A[i].lca);
}
rep(i,1,n) cnt[a[i]]=0;
Now=0;
printf("Case #%d:
",kase);
rep(i,1,m) printf("%d
",ans[i]);
}
}
以上是关于Nowcoder挑战赛39F(模板树上莫队)的主要内容,如果未能解决你的问题,请参考以下文章