zoukankan      html  css  js  c++  java
  • hdu 3974 dfs时间戳+线段树

    题意:

    1. 一个公司里面每个员工都有一个顶头上司,一旦给某个员工分配任务后,这个员工以及该员工的所有下属都在做该任务。 
    2.     有若干操作,分配给员工任务以及查询该员工正在执行的任务。

    题解:

            典型的更新字树的操作,用时间戳来区分子树,然后用线段树做区间的修改和查询。简单介绍一下时间戳(按照dfs的顺寻把一个点第一次遍历的时间点 以及最后一次也就是第二次遍历到的时间点保存下来 具体看下图 会发现一个点的第一次和第二次的时间包含了同样标记的子节点第一次遍历的时间)

    序列话之后,用线段树维护查询就好咯,注意一下建树的时候,大小别搞错了,,    

    上代码:

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <map>
    #include <cstring>
    #include <vector>
    #define maxn 50010
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    using namespace std;
    vector<int > edge[maxn];
    int n,ret;
    int in[maxn*2],out[maxn*2]; // 这里的范围要注意一下
    int lazy[maxn*4],val[maxn*4];
    int vis[maxn];
    void init()
    {
        ret=0;
        for(int i=0;i<=n;i++)
        {
            edge[i].clear();
            vis[i]=0;
        }
    }
    void dfs(int x,int fa)
    {
        in[x]=++ret;
        int len=edge[x].size();
        for(int i=0;i<len;i++)
        {
            if(edge[x][i]!=fa)
            {
                dfs(edge[x][i],x);
            }
        }
        out[x]=ret;
    }
    void build(int l,int r,int rt)
    {
        lazy[rt]=-1;
        val[rt]=-1;
        if(l==r) return;
        int m=(l+r)/2;
        build(lson);
        build(rson);
    }
    void pushdown(int rt)
    {
        if(lazy[rt]!=-1)
        {
            val[rt<<1]=lazy[rt];
            val[rt<<1|1]=lazy[rt];
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            lazy[rt]=-1;
        }
    }
    void update(int L,int R,int key,int l,int r,int rt)
    {
        if(L<=l && r<=R)
        {
            lazy[rt]=val[rt]=key;
            return;
        }
        pushdown(rt);
        int m=(l+r)/2;
        if(L<=m) update(L,R,key,lson);
        if(R>m) update(L,R,key,rson);
    }
    void query(int L,int R,int l,int r,int rt)
    {
        if(L<=l && r<=R)
        {
            cout<<val[rt]<<endl;
            return;
        }
        pushdown(rt);
        int m=(l+r)/2;
        if(L<=m) query(L,R,lson);
        if(R>m) query(L,R,rson);
    }
    int main()
    {
        int t,Case=0;
        cin>>t;
        while(t--)
        {
            cin>>n;
            init();
            for(int i=1;i<n;i++)
            {
                int x,y;
                scanf("%d %d",&x,&y);
                vis[x]=1;
               // edge[x].push_back(y);
                edge[y].push_back(x);
            }
            for(int i=1;i<=n;i++)
            {
                if(vis[i]==0)
                {
                    dfs(i,i);
                    break;
                }
            }
            build(1,ret,1);// 对dfs序建树
    
            printf("Case #%d:
    ",++Case);
            int q;
            cin>>q;
            while(q--)
            {
                char op[100];
                cin>>op;
                if(op[0]=='C')
                {
                    int x;
                    scanf("%d",&x);
                    query(in[x],in[x],1,ret,1);
                }
                else
                {
                    int x,y;
                    scanf("%d %d",&x,&y);
                    update(in[x],out[x],y,1,ret,1);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    闲谈系列之一——数据库主键GUID
    一个简单通用权限管理系统,求各位帮忙看看
    php 计算指定年份的周总数与及第几周的开始日期和结束日期(从周一开始)
    创建虚拟机流程详细过程链接
    阿里云CDN加速设置
    sublime Text3 快捷键
    Linux命令(centos7)
    分布式数据库
    mysql 分区和分表
    Linux crontab 命令格式与详细例子
  • 原文地址:https://www.cnblogs.com/z1141000271/p/8343426.html
Copyright © 2011-2022 走看看