zoukankan      html  css  js  c++  java
  • 遥远的国度 bzoj3083

    分析:

    这个题一看就是裸的树剖...

    唯一值得考虑的就是它的根一直在变化,我们可以这样想,如果假根在这个点的子树外,那么直接将这个点的子树作为答案区间,如果在子树内,则相对复杂,我们假设son为root所在的节点x的儿子的子树内的儿子编号,那么答案就是min(1到idx[son]-1,idx[son]+siz[son]到n),而如何求son...(这题数据水,暴力可过)详情请见代码,是树剖的一种应用。

    本人wa了一天(没有考虑到ro0t==x的请况),在这种情况下,直接查1-n的最小值就行

    附上代码:

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <iostream>
    using namespace std;
    #define N 300005
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    struct node
    {
        int to,next;
    }e[N<<1];
    int head[N],cnt,dep[N],fa[N],rot,anc[N],n,Q,siz[N],son[N],idx[N],tims,p[N];
    long long minn[N<<2],cov[N<<2],a[N];
    void add(int x,int y)
    {
        e[cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt++;
        return ;
    }
    void dfs1(int x,int from)
    {
        fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
        for(int i=head[x];i!=-1;i=e[i].next)
        {
            int to1=e[i].to;
            if(to1!=from)
            {
                dfs1(to1,x);
                siz[x]+=siz[to1];
                if(siz[son[x]]<siz[to1])son[x]=to1;
            }
        }
    }
    void dfs2(int x,int top)
    {
        anc[x]=top;idx[x]=++tims;p[tims]=x;
        if(son[x])dfs2(son[x],top);
        for(int i=head[x];i!=-1;i=e[i].next)
        {
            int to1=e[i].to;
            if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1);
        }
    }
    void PushUp(int rt)
    {
        minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
    }
    void PushDown(int rt)
    {
        if(cov[rt])
        {
            cov[rt<<1]=cov[rt];
            minn[rt<<1]=cov[rt];
            cov[rt<<1|1]=cov[rt];
            minn[rt<<1|1]=cov[rt];
            cov[rt]=0;
        }
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            minn[rt]=a[p[l]];
            return ;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        PushUp(rt);
    }
    void Update(int L,int R,long long c,int l,int r,int rt)
    {
        if(L<=l&&r<=R){cov[rt]=minn[rt]=c;return ;}
        PushDown(rt);int m=(l+r)>>1;
        if(m>=L)Update(L,R,c,lson);
        if(m<R)Update(L,R,c,rson);
        PushUp(rt);
    }
    long long query(int L,int R,int l,int r,int rt)
    {
        if(L>R)return 1ll<<32;
        if(L<=l&&r<=R)return minn[rt];
        PushDown(rt);int m=(l+r)>>1;long long ret=1ll<<32;
        if(m>=L)ret=min(query(L,R,lson),ret);
        if(m<R)ret=min(query(L,R,rson),ret);
        PushUp(rt);
        return ret;
    }
    void get_lca_Update(int x,int y,long long c)
    {
        while(anc[x]!=anc[y])
        {
            if(dep[anc[x]]<dep[anc[y]])swap(x,y);
            Update(idx[anc[x]],idx[x],c,1,n,1);
            x=fa[anc[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        Update(idx[x],idx[y],c,1,n,1);
    }
    int get_lca(int x,int y)
    {
        if(anc[x]==anc[y])return son[y];
        while(anc[fa[anc[x]]]!=anc[y])
        {
            x=fa[anc[x]];
        }
        if(fa[anc[x]]!=y)return son[y];
        return anc[x];
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&Q);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        dfs1(1,0);
        dfs2(1,1);
        build(1,n,1);
        scanf("%d",&rot);
        while(Q--)
        {
            int op,x,y;long long z;
            scanf("%d%d",&op,&x);
            //for(int i=1;i<=n;i++)printf("%d ",query(idx[i],idx[i],1,n,1));
            //	puts("");
            if(op==3)
            {
                if(rot==x)printf("%lld
    ",query(1,n,1,n,1));
                else if(idx[rot]>=idx[x]+siz[x]||idx[rot]<=idx[x])
                    printf("%lld
    ",query(idx[x],idx[x]+siz[x]-1,1,n,1));
                else
                {
                    int t=get_lca(rot,x);
                    printf("%lld
    ",min(query(1,idx[t]-1,1,n,1),query(idx[t]+siz[t]-1,n,1,n,1)));
                }
            }else if(op==2)
            {
                scanf("%d%lld",&y,&z);
                // int a=query(idx[x],idx[x],1,n,1),b=query(idx[y],idx[y],1,n,1);
                get_lca_Update(x,y,z);
                // Update(idx[x],idx[x],a,1,n,1),Update(idx[y],idx[y],b,1,n,1);
            }else rot=x;
        }
        return 0;
    }
    

      

  • 相关阅读:
    【ASP.NET】服务器控件大演练与实例分析
    【利用存储过程和三层架构完成新闻发布】
    【软件工程】web规格开发全过程
    【数据库】如何解决数据库附加失败问题
    【框架设计】异常
    【数据库】SqlCommand的几个易忽视的执行操作
    【ASP.NET】asp.net 页面调用服务端对象值
    【c#迭代器】
    【框架设计】CLR寄宿和应用程序域
    【ASP.NET】演绎GridView基本操作事件
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9079323.html
Copyright © 2011-2022 走看看