Assign the task //线段树+dfs序

本文探讨了一种使用线段树和深度优先搜索序(DFS序)来高效解决公司任务分配问题的方法。在一个有层级结构的公司中,任务可以被分配给员工及其所有下属,通过构建线段树并利用DFS序,我们能够快速地进行任务的分配与查询。文章详细介绍了如何利用这些数据结构来维护和更新员工的任务状态。

链接点这里

题意: 一个公司n个人,每个人都有上司,除了最大的boss,并且一个人上司的上司仍是他的上司,现在给某个人安排一项任务,等同于给他和他的下属安排这项命令,现在要给某个人赋予任务,或查询某个人现在的任务。

解析: 这道题的线段树的单点查询与区间更新很好维护,主要是怎样找对应人在线段树中的位置,利用dfs序即可解决。详细内容看代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int inf=0x3f3f3f3f;
const int maxn=5e4+10;
#define ls p<<1
#define rs p<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define faster ios::sync_with_stdio(0),cin.tie(0)
int t,m,n;
vector<int> e[maxn];
bool vis[maxn];
int st[maxn],en[maxn],ti;
int ma[maxn<<2],tag[maxn<<2];
void dfs(int u){//有向图跑dfs简单
    st[u]=++ti;
    for(int i=0;i<(int)e[u].size();i++){
        dfs(e[u][i]);
    }
    en[u]=ti;
}
void pushdown(int p){//下传标记
    if(tag[p]==-1)return;
    ma[ls]=ma[rs]=tag[ls]=tag[rs]=tag[p];
    tag[p]=-1;
}
void build(int l,int r,int p){
    tag[p]=-1;
    if(l==r){
        ma[p]=-1;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int L,int R,int c,int l,int r,int p){
    if(L<=l&&r<=R){
        ma[p]=tag[p]=c;
        return;
    }
    pushdown(p);//是否要下传标记
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,lson);
    if(R>m)update(L,R,c,rson);
}
int query(int x,int l,int r,int p){
    if(l==r)return ma[p];
    pushdown(p);
    int m=(l+r)>>1;
    if(x<=m)return query(x,lson);
    else return query(x,rson);
}
void see(){
    for(int i=1;i<=n;i++){
        cout<<st[i]<<" "<<en[i]<<'\n';
    }
}
int main()
{
    scanf("%d",&t);
    for(int k=1;k<=t;k++){
        scanf("%d",&n);
        ti=0;
        for(int i=1;i<=n;i++)e[i].clear(),vis[i]=0;
        for(int i=1;i<=n-1;i++){
            int u,v;scanf("%d%d",&u,&v);
            e[v].push_back(u);
            vis[u]=1;
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){//最大boss
                dfs(i);break;
            }
        }
        printf("Case #%d:\n",k);
        scanf("%d",&m);
        build(1,n,1);
        while(m--){
            char op;int x,y;
            cin>>op;
            if(op=='C'){
                scanf("%d",&x);//x在线段树中的位置就是st[x]
                cout<<query(st[x],1,n,1)<<'\n';
            }
            else {
                scanf("%d%d",&x,&y);//x在线段树中对应的区间就是(st[x],en[x])
                update(st[x],en[x],y,1,n,1);
            }
        }
        //see();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值