zoukankan      html  css  js  c++  java
  • Nowcoder挑战赛39F(模板树上莫队)

    Nowcoder挑战赛39F(模板树上莫队)

    题意:

    给定一棵树,求两点路径上的不同权值个数和权值是k的倍数的个数

    分析:

    第二问可以直接离线询问,暴力\(n\sqrt{n}\)枚举因数更新答案,路径作差

    第一问是树上莫队模板题

    树上莫队:在 括号序列 上跑莫队,对于单链和双链要分类讨论,更改权值上也有细微差别,还要特判LCA的情况

    合理压行和利用C++11有效缩短代码

    不知道官方题解是啥么东西,复杂度就是\(O(m\sqrt{n})\),而且上界很松

    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:\n",kase);
    		rep(i,1,m) printf("%d\n",ans[i]);
    	}
    }
    
    
  • 相关阅读:
    HDU 1063 Exponentiation
    HDU 1261 字串数
    HDU 1715 大菲波数
    HDU 1002 A + B Problem II
    csharp 復制DataTable修改某列的值
    解决IE6下透明PNG图片有灰底的解决方案
    webform TextBox以一条横线显示 兼容各主流瀏覽器 .
    SQL 工齡計算
    csharp Format CultureInfo
    Csharp Winform TextBox 樣式以一條橫線顯示
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12724013.html
Copyright © 2011-2022 走看看