2019.03.21【SPOJ-QTREE3】Query on a tree again!(轻重链剖分)

传送门


解析:

树链剖分裸题啊。。。

我们每个重链开一个set按照深度维护一下黑点,每次查找只需要跳重链的同时看一下链上最浅的黑点在不在 v v v上面就行了。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re char c;
		while(!isdigit(c=gc()));re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

using std::cout;
cs int N=1e5+5;
int n,q;
std::vector<int> e[N];
inline void addedge(int u,int v){
	e[u].push_back(v);
	e[v].push_back(u);
}

int dep[N],fa[N],top[N],siz[N],son[N];
void dfs1(int u){
	siz[u]=1;
	for(int &v:e[u])
	if(v^fa[u]){
		fa[v]=u;
		dep[v]=dep[u]+1;
		dfs1(v);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}

void dfs2(int u){
	if(son[u]){
		top[son[u]]=top[u];
		dfs2(son[u]);
	}
	else return ;
	for(int &v:e[u])
	if(v!=fa[u]&&v!=son[u]){
		top[v]=v;
		dfs2(v);
	}
}

struct cmp{bool operator()(cs int &u,cs int &v){return dep[u]<dep[v];}};
std::set<int,cmp> s[N];

bool col[N];

signed main(){
	n=getint();q=getint();
	for(int re i=1;i<n;++i)addedge(getint(),getint());
	dfs1(1);top[1]=1;
	dfs2(1);
	while(q--){
		switch(getint()){
			case 0:{
				int u=getint();
				col[u]^=1;
				if(col[u])s[top[u]].insert(u);
				else s[top[u]].erase(u);
				break;
			}
			case 1:{
				int v=getint(),ans=-1;
				while(top[v]!=1){
					if(!s[top[v]].empty()&&dep[*s[top[v]].begin()]<=dep[v])ans=*s[top[v]].begin();
					v=fa[top[v]];
				}
				if(!s[1].empty()&&dep[*s[1].begin()]<=dep[v])ans=*s[1].begin();
				cout<<ans<<"\n";
				break;
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值