T3
牛半仙的妹子Tree
https://ac.nowcoder.com/acm/contest/7609/C
C题考虑这样一个子问题:给定树上的点集 和询问点
,判断是否存在
,满足
,其中
为两点路径的边数,
为当前时间戳,
为
加入的时间戳。
硬拆式子
其中 表示
到根路径经过的边数。
这个 不太好搞,但注意到
取
的公共祖先时,式子
在 处取得最大值,所以只需要维护所有公共祖先就可以了,也就是修改和查询直接操作所有祖先。
感性理解就是,如果在更早的祖先处绕了远路,肯定只会更合法。
对每个点维护初值 ,然后树链剖分+标记永久化线段树
复杂度
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> #define MAXN 100005 #define INF 0x3f3f3f3f using namespace std; inline int read() { int ans=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } vector<int> e[MAXN]; int dis[MAXN],fa[MAXN],siz[MAXN],son[MAXN]; void dfs(int u,int f) { fa[u]=f,siz[u]=1; for (int i=0;i<(int)e[u].size();i++) if (e[u][i]!=f) { dis[e[u][i]]=dis[u]+1; dfs(e[u][i],u); siz[u]+=siz[e[u][i]]; if (siz[e[u][i]]>siz[son[u]]) son[u]=e[u][i]; } } int dfn[MAXN],pos[MAXN],tp[MAXN],tim; void dfs(int u) { pos[dfn[u]=++tim]=u; if (son[u]) tp[son[u]]=tp[u],dfs(son[u]); for (int i=0;i<(int)e[u].size();i++) if (e[u][i]!=fa[u]&&e[u][i]!=son[u]) tp[e[u][i]]=e[u][i],dfs(e[u][i]); } #define lc p<<1 #define rc p<<1|1 int tag[MAXN<<2],mxd[MAXN<<2],ans[MAXN<<2],cl[MAXN<<2]; inline void update(int p){ans[p]=min(tag[p]-2*mxd[p],min(ans[lc],ans[rc]));} inline void clear(int p){tag[p]=ans[p]=INF,cl[p]=1;} inline void pushdown(int p){if (cl[p]) clear(lc),clear(rc),cl[p]=0;} void build(int p,int l,int r) { tag[p]=ans[p]=INF; if (l==r) return (void)(mxd[p]=dis[pos[l]]); int mid=(l+r)>>1; build(lc,l,mid),build(rc,mid+1,r); mxd[p]=max(mxd[lc],mxd[rc]); } void modify(int p,int l,int r,int ql,int qr,int v) { if (ql<=l&&r<=qr) return (void)(ans[p]=min(ans[p],(tag[p]=min(tag[p],v))-2*mxd[p])); if (qr<l||r<ql) return; int mid=(l+r)>>1; pushdown(p); modify(lc,l,mid,ql,qr,v),modify(rc,mid+1,r,ql,qr,v); update(p); } int query(int p,int l,int r,int ql,int qr,int v) { if (ql<=l&&r<=qr) return min(ans[p],v-2*mxd[p]); if (qr<l||r<ql) return INF; int mid=(l+r)>>1; pushdown(p); v=min(v,tag[p]); return min(query(lc,l,mid,ql,qr,v),query(rc,mid+1,r,ql,qr,v)); } int n,m; inline void modify(int x,int v){for (;x;x=fa[tp[x]]) modify(1,1,n,dfn[tp[x]],dfn[x],v);} inline int query(int x,int ans=INF){for (;x;x=fa[tp[x]]) ans=min(ans,query(1,1,n,dfn[tp[x]],dfn[x],INF));return ans;} int main() { n=read(),m=read(); for (int i=1;i<n;i++) { int u,v; u=read(),v=read(); e[u].push_back(v),e[v].push_back(u); } dfs(1,0); dfs(tp[1]=1); build(1,1,n); for (int i=1;i<=m;i++) { int t,x; t=read(),x=read(); if (t==1) modify(x,dis[x]+i); if (t==2) clear(1); if (t==3) puts(query(x)<=i-dis[x]? "wrxcsd":"orzFsYo"); } return 0; }