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;
}
全部评论

相关推荐

4 收藏 评论
分享
牛客网
牛客企业服务