BZOJ 3306 树

Posted ziliuziliu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3306 树相关的知识,希望对你有一定的参考价值。

dfs序建线段树+分类讨论+写的有点长。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 100500
#define maxe 200500
#define inf 2147483646
using namespace std;
int n,m,w[maxv],dfn[maxv],fdfn[maxv],g[maxv],nume=0,x,y,cnt=0,dis[maxv],mx[maxv],anc[maxv][23];
int tot=0,root,ls[maxv<<2],rs[maxv<<2],val[maxv<<2],nrt;
char s[4];
struct edge
{
    int v,nxt;
}e[maxe];
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs(int x,int fath)
{
    dfn[x]=++cnt;mx[x]=dfn[x];fdfn[cnt]=x;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v==fath) continue;
        dis[v]=dis[x]+1;
        dfs(v,x);anc[v][0]=x;
        mx[x]=max(mx[x],mx[v]);
    }
}
void get_table()
{
    for (int e=1;e<=20;e++)
        for (int i=1;i<=n;i++)
            anc[i][e]=anc[anc[i][e-1]][e-1];
}
void build(int &now,int left,int right)
{
    now=++tot;
    if (left==right)
    {
        val[now]=w[fdfn[left]];
        return;
    }
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    val[now]=min(val[ls[now]],val[rs[now]]);
}
void modify(int now,int left,int right,int pos)
{
    if ((left==right) && (left==pos))
    {
        val[now]=w[fdfn[left]];
        return;
    }
    int mid=(left+right)>>1;
    if (pos<=mid) modify(ls[now],left,mid,pos);
    else modify(rs[now],mid+1,right,pos);
    val[now]=min(val[ls[now]],val[rs[now]]);
}
int ask(int now,int left,int right,int l,int r)
{
    if (l>r) return inf;
    if ((l<=0) || (r>=n+1)) return inf;
    if ((left==l) && (right==r)) return val[now];
    int mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r);
    else return min(ask(ls[now],left,mid,l,mid),ask(rs[now],mid+1,right,mid+1,r));
}
int find(int x,int pos)
{
    for (int e=20;e>=0;e--)
    {
        if (dis[anc[x][e]]>dis[pos])
            x=anc[x][e];
    }
    return x;
}
int main()
{
    freopen("cin.in","r",stdin);
    freopen("a.out","w",stdout);
    nrt=1;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&w[i]);
        if (x!=0) {addedge(i,x);addedge(x,i);}
    }
    dfs(1,1);
    get_table();
    build(root,1,n);
    for (int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]==V)
        {
            scanf("%d%d",&x,&y);
            w[x]=y;
            modify(root,1,n,dfn[x]);
        }    
        else if (s[0]==E) scanf("%d",&nrt);
        else
        {
            scanf("%d",&x);
            if (x==nrt) printf("%d\n",val[1]);
            else if ((dfn[nrt]>=dfn[x]) && (dfn[nrt]<=mx[x]))
            {
                int r=find(nrt,x);
                printf("%d\n",min(ask(root,1,n,1,dfn[r]-1),ask(root,1,n,mx[r]+1,n)));
            }
            else printf("%d\n",ask(root,1,n,dfn[x],mx[x]));
        }
    }
    return 0;
}

 

以上是关于BZOJ 3306 树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3306 树

[BZOJ3306]树

[BZOJ 3306]树(dfs序+线段树+倍增)

bzoj3306: 树(dfs序+倍增+线段树)

BZOJ3306: 树

[bzoj5379]Tree_dfs序_线段树_倍增lca