Solution

一些闲话:发现之前写的题解像一坨屎,但是由于发的很快,所以阅读量也挺多的 🤔。

转化题意,询问节点为 \(v\) 时,如果存在节点 \(u\) 满足 \(\text{dis}(u,v)\leqslant t_v-t_u\),也就是 \(d_u+d_v-2d_{\text{lca}(u,v)}\leqslant t_v-t_u\),那么节点 \(v\) 就无视了牛半仙。

然后我就懵了,不知道该怎么处理。但其实很简单,类似于树状数组、线段树、分块之类优化的思路:平均查询与插入的时间复杂度。我们考虑将 \(u\) 的数据先插入,再用 \(v\) 来查询。

用这个思路来转化限制,即 \(d_u+t_u-2 d_{\text{lca}(u,v)}\leqslant t_v-d_v\).

\(\text{lca}\) 似乎不太好处理,由于 \(u\)\(\text{lca}\) 只会是 \(u\) 到根的链上的点,\(v\) 同理,可以用树剖来做这道题。可以发现 \(-2d_{\text{lca}(u,v)}\) 只和它所在的点有关系,那么直接向 \(u\) 到根的链插入 \(d_u+t_u\),用变量 \(\rm val\) 维护这个部分的最小值,再预处理 \(\rm maxd\) 为深度最大值,就可以维护 \(d_u+t_u-2 d_{\text{lca}(u,v)}\) 的最小值。查询就只用查询 \(v\) 到根的链上的最小值再和 \(t_v-d_v\) 比较即可。注意这个正确性取决于对于同一个 \(u\),它修改的链上深度最深的点一定是更优的,也就是一定会取到 \(u\)\(v\)\(\rm lca\).

Code

#include <cstdio>

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}

#include <vector>
using namespace std;

const int maxn=1e5+5,inf=0x3f3f3f3f;

int maxd[maxn<<2],n,m,dfn[maxn],siz[maxn],f[maxn],dep[maxn],son[maxn],pos[maxn],Dfn,tp[maxn],ans[maxn<<2],val[maxn<<2];
vector <int> e[maxn];
bool tag[maxn<<2];

void dfs1(int u,int fa) {
	siz[u]=1,f[u]=fa,dep[u]=dep[fa]+1;
	for(int i=0;i<e[u].size();++i) {
		int v=e[u][i];
		if(v==fa) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
}

void dfs2(int u) {
	pos[dfn[u]=++Dfn]=u;
	if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]);
	for(int i=0;i<e[u].size();++i) {
		int v=e[u][i];
		if(v==f[u]||v==son[u]) continue;
		tp[v]=v,dfs2(v);
	}
}

void clear(int x) {ans[x]=val[x]=inf; tag[x]=1;}

void Delete(int x) {
	if(tag[x]) clear(x<<1),clear(x<<1|1),tag[x]=0;
	val[x<<1]=Min(val[x<<1],val[x]);
	val[x<<1|1]=Min(val[x<<1|1],val[x]);
	ans[x<<1]=Min(ans[x<<1],val[x<<1]-2*maxd[x<<1]);
	ans[x<<1|1]=Min(ans[x<<1|1],val[x<<1|1]-2*maxd[x<<1|1]);
}

void pushUp(int u) {
	if(!u) return;
	ans[u]=Min(val[u]-2*maxd[u],Min(ans[u<<1],ans[u<<1|1]));
}

void modify(int o,int l,int r,int L,int R,int k) {
	if(l>R||r<L) return;
	if(l>=L&&r<=R) return (void) (ans[o]=Min(ans[o],(val[o]=Min(val[o],k))-2*maxd[o]));
	int mid=l+r>>1;
	Delete(o);
	modify(o<<1,l,mid,L,R,k); modify(o<<1|1,mid+1,r,L,R,k);
	pushUp(o);
} 

void build(int o,int l,int r) {
	ans[o]=val[o]=inf;
	if(l==r) return (void) (maxd[o]=dep[pos[l]]);
	int mid=l+r>>1;
	build(o<<1,l,mid); build(o<<1|1,mid+1,r);
	maxd[o]=Max(maxd[o<<1],maxd[o<<1|1]);
}

int query(int o,int l,int r,int L,int R) {
	if(l>R||r<L) return inf;
	if(l>=L&&r<=R) return ans[o];
	int mid=l+r>>1;
	Delete(o);
	return Min(query(o<<1,l,mid,L,R),query(o<<1|1,mid+1,r,L,R));
}

void change(int u,int w) {
	for(;u;u=f[tp[u]]) modify(1,1,n,dfn[tp[u]],dfn[u],w);
}

int ask(int u) {
	int ret=inf;
	for(;u;u=f[tp[u]]) ret=Min(ret,query(1,1,n,dfn[tp[u]],dfn[u]));
	return ret;
}

int main() {
	int u,v;
	n=read(9),m=read(9);
	rep(i,1,n-1) {
		u=read(9),v=read(9);
		e[u].push_back(v),e[v].push_back(u);
	}
	dfs1(1,0),tp[1]=1,dfs2(1); build(1,1,n);
	rep(i,1,m) {
		u=read(9),v=read(9);
		if(u==1) change(v,dep[v]+i);
		else if(u==2) clear(1);
		else puts(ask(v)<=i-dep[v]?"wrxcsd":"orzFsYo");
	}
	return 0;
}
posted on 2020-10-23 21:58  Oxide  阅读(247)  评论(0编辑  收藏  举报