其他分享
首页 > 其他分享> > C20220712T3 牛半仙的妹子Tree

C20220712T3 牛半仙的妹子Tree

作者:互联网

给定一棵树,要求执行3种操作:

  1. 给树上某一结点涂色,从下一次操作起每一次向周围传染一个单位。
  2. 树上所有点变为正常
  3. 询问某个点是否被感染。

\(n,m\leq 10^5\)。


首先想到暴力做法,用栈维护现在被感染的节点以及感染时间,那么对于操作1,2都好解决,对于操作3需要遍历栈并求出是否有节点可以传染到它(即 \(dis(u,v)\leq time\_now-time\_u\) )。实测可以拿40。

考虑优化思路,可以发现这题的瓶颈在于栈中点太多,那么可以考虑当栈中点过多时可以直接 \(dfs\) 一边,将答案记录在节点上,然后清空,保证对于之前的点可以 \(O(1)\) 查询,同时若出现操作2就直接打上标记,表示之前的点被清空。对于大块整体处理,小块暴力,就是一个类似分块的做法。

struct edge{
	ll to,nxt;
}e[200005];

struct node{
	ll pos,t;
	node(ll x,ll y){
		pos=x;
		t=y;
	}
	node(){pos=0;t=0;}
}stabf[100005],sta[100005];

ll head[100005],ecnt;

void adde(ll u,ll v){
	e[++ecnt].nxt=head[u];
	e[ecnt].to=v;
	head[u]=ecnt;
}
std::queue<node> q;
ll n,m,flag,fa[100005][20],dep[100005],minn[100005],vis[100005];//17
ll top=-1,bj,block,topbf=-1;


void dfs(ll x){
	dep[x]=dep[fa[x][0]]+1;
	FOR(i,1,17){
		fa[x][i]=fa[fa[x][i-1]][i-1];
	}
	for(rg ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y==fa[x][0])
			continue;
		fa[y][0]=x;
		dfs(y);
	}
}

void bfs(){
	while(q.size())
		q.pop();
	memset(minn,0x3f,sizeof(minn));
	memset(vis,0,sizeof(vis));
	FOR(i,0,top){
		stabf[++topbf]=sta[i];
	}
	FOR(i,0,topbf){
		minn[stabf[i].pos]=std::min(minn[stabf[i].pos],stabf[i].t);
	}
	q.push(stabf[0]);
	ll rr=1;
	while(q.size()){
		node u=q.front();
		q.pop();
		for(rg ll i=head[u.pos];i;i=e[i].nxt){
			int v=e[i].to;
			if(vis[v]==0){
				vis[v]=1;
				minn[v]=std::min(minn[v],minn[u.pos]+1);
				q.push(node(v,minn[v]));
				if(minn[v]==stabf[rr].t){
					vis[stabf[rr].pos]=1;
					q.push(stabf[rr]);
					++rr;
				}
			}
		}
	}
}

ll dis(ll x,ll y){
	ll ret=0;
	if(dep[x]<dep[y])
		std::swap(x,y);
	ROF(i,17,0){
		if(dep[fa[x][i]]>=dep[y]){
			ret+=1<<i;
			x=fa[x][i];
		}
	}
	ROF(i,17,0){
		if(fa[x][i]!=fa[y][i]){
			ret+=1<<(1+i);
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	if(x!=y)
		ret+=2;
	return ret;
}



int main(){
	memset(minn,0x3f,sizeof(minn));
	n=in(),m=in();
	block=900;
	FOR(i,1,n-1){
		ll u=in(),v=in();
		adde(u,v);
		adde(v,u);
	}
	dfs(1);
	FOR(z,1,m){
		if(z%block==0){
			bfs();
			top=-1;
			bj=0;
		}
		ll op=in(),x=in();
		if(op==1){
			sta[++top]=node(x,z);
		}
		if(op==2){
			top=-1;
			topbf=-1;
			bj=1;
		}
		if(op==3){
			ll flag=0;
			FOR(i,0,top){
				if(dis(sta[i].pos,x)<=(z-sta[i].t)){
					puts("wrxcsd");
					flag=1;
					break;
				}
			}
			if(bj==0 && flag==0){
				if(minn[x]<=z){
					puts("wrxcsd");
					continue;
				}
			}
			if(flag==0){
				puts("orzFsYo");
			}
		}
	}
	return 0;
} 

标签:半仙,minn,ll,Tree,pos,C20220712T3,100005,fa,stabf
来源: https://www.cnblogs.com/zhouzizhe/p/16639832.html