zoukankan      html  css  js  c++  java
  • Codeforces 1320E. Treeland and Viruses 题解

    题目链接:E. Treeland and Viruses
    题目大意:有一棵有(n)个节点的树,(q)次询问(询问互相独立),每次给定(k_i)个颜色,每个颜色有一个起始点(v_j)和移动速度(s_j),每一个颜色在每一次操作中会使它周围没有被染色的连通块上与它的距离不超过(s_j)的点全部染为这一个颜色,每一轮中,颜色从(1)(k_i)依次开始操作,一直到所有点全部被染色为止,再询问(m_i)个关键点的颜色。


    题解:这一道题一看就像是建虚树,先考虑把虚树建出来,由于某些颜色会被阻断,所以不能够直接用树上路径长度求出,所以每一个点只能更新与它相邻的点,所以,先用孩子更新父亲,然后再用父亲更新孩子,这样做两遍之后就可以得出答案。至于依次染色的限制,可以直接用优先级解决掉(以到达时间为第一关键字,颜色种类为第二关键词)。思路还是挺简洁明了的。

    时间复杂度(O(n ext{log}n)),不过我的代码应该带上了一个很大的常数,如果用树链剖分求LCA应该会快不少。

    感觉自己的语文水平不太够啊,如果真的看不懂就看代码吧,代码应该也不难理解。

    下面是代码:

    #include <vector>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    void read(int &a){
    	a=0;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		a=(a<<1)+(a<<3)+(c^48);
    		c=getchar();
    	}
    }
    const int Maxn=200000;
    int head[Maxn+5],arrive[Maxn<<1|5],nxt[Maxn<<1|5],tot;
    void add_edge(int from,int to){
    	arrive[++tot]=to;
    	nxt[tot]=head[from];
    	head[from]=tot;
    }
    int n,q;
    int fa[18][Maxn+5];
    int dep[Maxn+5];
    int dfn[Maxn+5],out[Maxn+5],dfn_tot;
    void init_dfs(int u){
    	dfn[u]=++dfn_tot;
    	dep[u]=dep[fa[0][u]]+1;
    	for(int i=1;fa[i-1][fa[i-1][u]];i++){
    		fa[i][u]=fa[i-1][fa[i-1][u]];
    	}
    	for(int i=head[u];i;i=nxt[i]){
    		int v=arrive[i];
    		if(v==fa[0][u]){
    			continue;
    		}
    		fa[0][v]=u;
    		init_dfs(v);
    	}
    	out[u]=dfn_tot;
    }
    int find_lca(int u,int v){
    	if(dep[u]<dep[v]){
    		swap(u,v);
    	}
    	for(int i=17;i>=0;i--){
    		if(dep[fa[i][u]]>=dep[v]){
    			u=fa[i][u];
    		}
    	}
    	if(u==v){
    		return u;
    	}
    	for(int i=17;i>=0;i--){
    		if(fa[i][u]!=fa[i][v]){
    			u=fa[i][u];
    			v=fa[i][v];
    		}
    	}
    	return fa[0][u];
    }
    int find_dis(int u,int v){
    	return dep[u]+dep[v]-(dep[find_lca(u,v)]<<1);
    }//正常的倍增求LCA,树上距离等等
    int sp[Maxn+5],type[Maxn+5];
    int f[Maxn+5];
    int lim[Maxn<<2|5],lim_len;
    int pa[Maxn+5];
    int imp[Maxn+5];
    int st[Maxn+5],st_top;
    int get_time(int u,int v){
    	return (find_dis(u,v)+sp[type[u]]-1)/sp[type[u]];
    }//求出一个颜色的起始点到另一个点所需时间
    int merge(int u,int a,int b){
    	if(u==0){
    		return 0;
    	}
    	if(a==0){
    		return b;
    	}
    	if(b==0){
    		return a;
    	}
    	int dis_a=get_time(a,u),dis_b=get_time(b,u);
    	if(dis_a==dis_b){
    		return type[a]<type[b]?a:b;
    	}
    	return dis_a<dis_b?a:b;//双关键字
    }
    bool cmp(int p,int q){
    	return dfn[p]<dfn[q];
    }
    int main(){
    	read(n);
    	int u,v;
    	for(int i=1;i<n;i++){
    		read(u),read(v);
    		add_edge(u,v);
    		add_edge(v,u);
    	}
    	init_dfs(1);
    	read(q);
    	int k,m;
    	for(int i=1;i<=q;i++){
    		read(k),read(m);
    		lim_len=0;
    		for(int j=1;j<=k;j++){
    			read(u),read(v);
    			type[u]=j;
    			sp[j]=v;
    			f[u]=u;
    			lim[++lim_len]=u;
    		}
    		for(int j=1;j<=m;j++){
    			read(u);
    			lim[++lim_len]=u;
    			imp[j]=u;
    		}
    		sort(lim+1,lim+1+lim_len,cmp);
    		for(int j=lim_len-1;j>0;j--){
    			lim[++lim_len]=find_lca(lim[j],lim[j+1]);
    		}
    		sort(lim+1,lim+1+lim_len,cmp);
    		lim_len=unique(lim+1,lim+1+lim_len)-lim-1;
    		st_top=0;
    		for(int j=1;j<=lim_len;j++){
    			while(st_top&&out[st[st_top]]<dfn[lim[j]]){
    				st_top--;
    			}
    			if(st_top){
    				pa[lim[j]]=st[st_top];
    			}
    			st[++st_top]=lim[j];
    		}//普通的建虚树过程
    		for(int j=lim_len;j>0;j--){
    			f[pa[lim[j]]]=merge(pa[lim[j]],f[pa[lim[j]]],f[lim[j]]);
    		}//用孩子去更新父亲(往祖先染)
    		for(int j=1;j<=lim_len;j++){
    			f[lim[j]]=merge(lim[j],f[lim[j]],f[pa[lim[j]]]);
    		}//用父亲来更新孩子(往孩子染)
    		for(int j=1;j<=m;j++){
    			printf("%d ",type[f[imp[j]]]);
    		}
    		puts("");
    		for(int j=1;j<=lim_len;j++){
    			type[lim[j]]=0;
    			f[lim[j]]=0;
    			pa[lim[j]]=0;
    		}//一定要清零清零清零!!!!
    	}
    	return 0;
    }
    
  • 相关阅读:
    jmter录制脚本、代理配置和操作
    Jmeter服务器性能压测之—QPS/RPS/TPS/RT/并发数/并发连接数/并发用户数/线程数/吞吐量等概念详解
    Chales 抓https 显示Unknown
    转:Jmeter-场景执行与结果收集、分析
    转:Jmeter-使用Stepping Thread Group插件来设置负载场景
    Jmeter ServerAgent
    AWVS13 破解
    Jenkins 配置邮箱服务器
    Linux + Jenkins + Jmeter
    系统故障处理
  • 原文地址:https://www.cnblogs.com/withhope/p/12394858.html
Copyright © 2011-2022 走看看