[BZOJ3306]树(dfs序)

20 篇文章 0 订阅

题目描述

传送门

题解

同BZOJ3083

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=1e5+5;
const int max_e=max_n;
const int max_tree=max_n*4;
const int INF=2147483647;

int n,m,N,fa,root,x,y;
int tot,point[max_n],next[max_e],v[max_e];
int a[max_n],father[max_n],in[max_n],out[max_n],val[max_n];
int tree[max_tree];

inline void addedge(int x,int y){++tot;next[tot]=point[x];point[x]=tot;v[tot]=y;}
inline void dfs(int x,int fa){
    father[x]=fa; in[x]=++N; val[N]=a[x];
    for (int i=point[x];i;i=next[i])
      if (v[i]!=fa)
        dfs(v[i],x);
    out[x]=N;
}
inline void update(int now){
    tree[now]=min(tree[now<<1],tree[now<<1|1]);
}
inline void build(int now,int l,int r){
    int mid=(l+r)>>1;
    if (l==r){
        tree[now]=val[l];
        return;
    }
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    update(now);
}
inline void point_change(int now,int l,int r,int x,int v){
    int mid=(l+r)>>1;
    if (l==r){
        tree[now]=v;
        return;
    }
    if (x<=mid) point_change(now<<1,l,mid,x,v);
    else point_change(now<<1|1,mid+1,r,x,v);
    update(now);
}
inline int query(int now,int l,int r,int lrange,int rrange){
    int mid=(l+r)>>1,ans=INF;
    if (lrange<=l&&r<=rrange) return tree[now];
    if (lrange<=mid) ans=min(ans,query(now<<1,l,mid,lrange,rrange));
    if (mid+1<=rrange) ans=min(ans,query(now<<1|1,mid+1,r,lrange,rrange));
    return ans;
}
inline int ask(int x){
    if (root==x) return query(1,1,N,1,N);
    if (!(in[root]>=in[x]&&in[root]<=out[x])) return query(1,1,N,in[x],out[x]);
    int ans=INF;
    for (int i=point[x];i;i=next[i])
      if (v[i]!=father[x]&&in[root]>=in[v[i]]&&in[root]<=out[v[i]]){
        if (1<=in[v[i]]-1) ans=min(ans,query(1,1,N,1,in[v[i]]-1));
        if (out[v[i]]+1<=N) ans=min(ans,query(1,1,N,out[v[i]]+1,N));
        break;
      }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i){
        scanf("%d%d",&fa,&a[i]);
        if (fa) addedge(fa,i);
        else root=i;
    }
    dfs(root,0);
    build(1,1,N);
    for (int i=1;i<=m;++i){
        char opt=getchar();
        while (opt!='V'&&opt!='E'&&opt!='Q') opt=getchar();
        if (opt=='V'){
            scanf("%d%d",&x,&y);
            point_change(1,1,N,in[x],y);
        }
        if (opt=='E'){
            scanf("%d",&x);
            root=x;
        }
        if (opt=='Q'){
            scanf("%d",&x);
            int ans=ask(x);
            printf("%d\n",ans);
        }
    }
}

手写栈

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_n=1e5+5;
const int max_e=max_n;
const int max_tree=max_n*4;
const int INF=2147483647;

int n,m,N,fa,root,x,y;
int tot,point[max_n],next[max_e],v[max_e];
int a[max_n],father[max_n],in[max_n],out[max_n],val[max_n];
int tree[max_tree];
int cur[max_n],strack[max_n];

inline void addedge(int x,int y){++tot;next[tot]=point[x];point[x]=tot;v[tot]=y;}
inline void dfs()
{
    int temp=0;
    in[root]=++N; val[N]=a[root];
    strack[++temp]=root;
    for (int i=1;i<=n;++i) cur[i]=point[i];
    while (temp)
    {
        int x=strack[temp];
        if (v[cur[x]]==father[x])
            cur[x]=next[cur[x]];
        if (!cur[x])
        {
            out[strack[temp]]=N;
            --temp;
            continue;
        }
        int vt=v[cur[x]];
        strack[++temp]=vt; father[vt]=x;
        in[vt]=++N; val[N]=a[vt];
        cur[x]=next[cur[x]];
    }
}
inline void update(int now){
    tree[now]=min(tree[now<<1],tree[now<<1|1]);
}
inline void build(int now,int l,int r){
    int mid=(l+r)>>1;
    if (l==r){
        tree[now]=val[l];
        return;
    }
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    update(now);
}
inline void point_change(int now,int l,int r,int x,int v){
    int mid=(l+r)>>1;
    if (l==r){
        tree[now]=v;
        return;
    }
    if (x<=mid) point_change(now<<1,l,mid,x,v);
    else point_change(now<<1|1,mid+1,r,x,v);
    update(now);
}
inline int query(int now,int l,int r,int lrange,int rrange){
    int mid=(l+r)>>1,ans=INF;
    if (lrange<=l&&r<=rrange) return tree[now];
    if (lrange<=mid) ans=min(ans,query(now<<1,l,mid,lrange,rrange));
    if (mid+1<=rrange) ans=min(ans,query(now<<1|1,mid+1,r,lrange,rrange));
    return ans;
}
inline int ask(int x){
    if (root==x) return query(1,1,N,1,N);
    if (!(in[root]>=in[x]&&in[root]<=out[x])) return query(1,1,N,in[x],out[x]);
    int ans=INF;
    for (int i=point[x];i;i=next[i])
      if (v[i]!=father[x]&&in[root]>=in[v[i]]&&in[root]<=out[v[i]]){
        if (1<=in[v[i]]-1) ans=min(ans,query(1,1,N,1,in[v[i]]-1));
        if (out[v[i]]+1<=N) ans=min(ans,query(1,1,N,out[v[i]]+1,N));
        break;
      }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i){
        scanf("%d%d",&fa,&a[i]);
        if (fa) addedge(fa,i);
        else root=i;
    }
    dfs();
    build(1,1,N);
    for (int i=1;i<=m;++i){
        char opt=getchar();
        while (opt!='V'&&opt!='E'&&opt!='Q') opt=getchar();
        if (opt=='V'){
            scanf("%d%d",&x,&y);
            point_change(1,1,N,in[x],y);
        }
        if (opt=='E'){
            scanf("%d",&x);
            root=x;
        }
        if (opt=='Q'){
            scanf("%d",&x);
            int ans=ask(x);
            printf("%d\n",ans);
        }
    }
}

总结

1A嘿嘿嘿

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值