HDU - 3974 Assign the task(dfs序列加线段树维护)

HDU - 3974 Assign the task
题 意:一个公司,每个员工都只有一个直接的上司,上司的上司是我的上司,下属的下属是我的下属。现在公司分配任务,T x y。将任务y分配给x以及他的下属。也就是说,x和他的下属同时收到任务。当x和他的下属同时收到任务时,他们会停下手中的工作去做任务y。现在m次操作。C x.询问x现在手中的任务.T x y:将任务y分配给x以及他的下
数据范围:
T<=50
N<=50000
X<=n
y<=1e9

输入样例:

1 
5 
4 3 
3 2 
1 3 
5 2 
5 
C 3 
T 2 1
 C 3 
T 3 2 
C 3

输出样例:

Case #1:
-1 
1 
2

这里写图片描述
dfs序列.
这里写图片描述

思 路:dfs序列记录好它和它子节点的开始和结束编号,加线段树维护。
2是[1,5],5是[2,2],3是[3,5],1是[4,4],4是[5,5]用一个start数组,一个end数组去储存就好,然后用线段树去维护.

收 获:学会了用线段树去维护dfs序列

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 5e4+5;
struct node{
    int to,next;
}edge[maxn];
int head[maxn],cnt,tot;
bool vis[maxn];
int start[maxn],en[maxn];
int sum[maxn<<2],lazy[maxn<<2];
int n,m;

void addedge(int u,int v){
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void init(){
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
    cnt = 0;
    tot = 0;
}

void dfs(int u){
    ++cnt;
    start[u] = cnt;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int to = edge[i].to;
        dfs(to);
    }
    en[u] = cnt;
}


void build(int l,int r,int rt){
    sum[rt] = -1;
    lazy[rt] = 0;
    if(l == r){
        return;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
}
void PushDown(int rt){
    if(lazy[rt]){
        lazy[rt<<1] = lazy[rt];
        lazy[rt<<1|1] = lazy[rt];
        sum[rt<<1] = sum[rt];
        sum[rt<<1|1] = sum[rt];
        lazy[rt] = 0;
    }
}
void update(int L,int R,int x,int l,int r,int rt){
    if(L<=l && r<=R){
        sum[rt] = x;
        lazy[rt] = 1;
        return ;
    }
    PushDown(rt);
    int m = (l+r)>>1;
    if(L<=m) update(L,R,x,lson);
    if(R > m) update(L,R,x,rson);
}
int query(int x,int l,int r,int rt){
    if(l == r){
        return sum[rt];
    }
    PushDown(rt);
    int m = (l+r)>>1;
    if(x<=m) query(x,lson);
    else query(x,rson);
}
int main(){
    int t;
    int Kase = 1;
    scanf("%d",&t);
    while(t--){
        printf("Case #%d:\n",Kase++);
        init();
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++){
            int u,v;
            scanf("%d %d",&v,&u);
            addedge(u,v);
            vis[v] = true;
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                dfs(i);
                break;
            }
        }

        build(1,cnt,1);
        scanf("%d",&m);
        char s[10];int l,r;
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            if(s[0] == 'C'){
                scanf("%d",&l);
                int ans = query(start[l],1,n,1);
                printf("%d\n",ans);
            }else{
                scanf("%d %d",&l,&r);
                update(start[l],en[l],r,1,n,1);
            }
        }
    }
    return 0;
}
/*
2
6 2 4
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值