• 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]);
    	}
    }
    
    
  • 相关阅读:
    1-Java类结构和main函数
    0-java概述
    2-python元组和列表
    SSH密码暴力破解及防御实战----防
    SQL注入攻击及防御详解
    XSS跨站攻防安全
    文件包含渗透----当我们无法进行上传渗透时另一种黑客攻击
    jspgou商城部署时报错:Could not open Hibernate Session for transaction; nested exception is org.hibernate.ex
    上传漏洞----看完之后你也是黑客(中国菜刀和kali)
    部署jenkins服务器出现Please wait while Jenkins is getting ready to work ...一直进不去该怎么办?
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12724013.html
Copyright © 2020-2023  润新知