Assign the task HDU - 3974

点击打开链接

利用dfs序将多叉树映射到线段树上

对于任意一个节点 在先序序列中每个子节点都在其后 而在后序序列中每个子节点都在其前 这样就确定了多叉树的一棵子树在线段树中的左右区间

 

#include <bits/stdc++.h>
using namespace std;

struct node1
{
    int l;
    int r;
    int laz;
    int val;
};

struct node2
{
    int l;
    int r;
};

struct node3
{
    int v;
    int next;
};

node1 tree[200010];
node2 point[50010];
node3 edge[50010];
int book[50010],first[50010];
int n,q,num;

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
    return;
}

void safari(int u,int fat)
{
    int i,v;
    point[u].l=num++;
    for(i=first[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fat)
        {
            safari(v,u);
        }
    }
    point[u].r=num-1;
    return;
}

void pushdown(int cur)
{
    tree[cur*2].laz=tree[cur].laz;
    tree[cur*2].val=tree[cur].laz;
    tree[cur*2+1].laz=tree[cur].laz;
    tree[cur*2+1].val=tree[cur].laz;
    tree[cur].laz=-1;
    return;
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].l=l;
    tree[cur].r=r;
    tree[cur].laz=-1;
    tree[cur].val=-1;
    if(l==r) return;
    m=(l+r)/2;
    build(l,m,cur*2);
    build(m+1,r,cur*2+1);
    return;
}

int query(int tar,int cur)
{
    if(tree[cur].l==tree[cur].r)
    {
        return tree[cur].val;
    }
    if(tree[cur].laz>=0) pushdown(cur);
    if(tar<=tree[cur*2].r) return query(tar,cur*2);
    else return query(tar,cur*2+1);
}

void update(int ll,int rr,int val,int cur)
{
    if(ll<=tree[cur].l&&tree[cur].r<=rr)
    {
        tree[cur].laz=val;
        tree[cur].val=val;
        return;
    }
    if(tree[cur].laz>=0) pushdown(cur);
    if(ll<=tree[cur*2].r) update(ll,rr,val,cur*2);
    if(rr>=tree[cur*2+1].l) update(ll,rr,val,cur*2+1);
    return;
}

int main()
{
    int t,cas,i,u,v;
    char ch[2];
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d",&n);
        memset(book,0,sizeof(book));
        memset(first,-1,sizeof(first));
        num=0;
        for(i=0;i<n-1;i++)
        {
            scanf("%d%d",&u,&v);
            book[u]=1;
            addedge(v,u);
        }
        num=1;
        for(i=1;i<=n;i++)
        {
            if(!book[i])
            {
                safari(i,-1);
                break;
            }
        }
        build(1,n,1);
        scanf("%d",&q);
        printf("Case #%d:\n",cas);
        while(q--)
        {
            scanf("%s",ch);
            if(ch[0]=='C')
            {
                scanf("%d",&u);
                printf("%d\n",query(point[u].l,1));
            }
            else
            {
                scanf("%d%d",&u,&v);
                update(point[u].l,point[u].r,v,1);
            }
        }
    }
    return 0;
}

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值