遥远的国度 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\n",query(1,n,1,n,1));
            else if(idx[rot]>=idx[x]+siz[x]||idx[rot]<=idx[x])
                printf("%lld\n",query(idx[x],idx[x]+siz[x]-1,1,n,1));
            else
            {
                int t=get_lca(rot,x);
                printf("%lld\n",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;
}

  

posted @ 2018-05-23 20:58  Winniechen  阅读(124)  评论(0编辑  收藏  举报