Assign the task HDU - 3974

题意:有一棵树,最开始每个节点权值都为-1,有两种操作,第一种查询当前节点的权值,第二种更改以当前节点为根的子树的所有点的权值。

思路:线段树+dfs序维护,据说这是线段树基本操作(瑟瑟发抖)

点击打开链接

#include<bits/stdc++.h>
#define read(x) scanf("%d",&x)
#define debug puts("###")
using namespace std;
const int maxn=5e5+10;
int task[maxn<<2],la[maxn<<2];
struct node{
    int to,next;
}edge[maxn];

int l1,l[maxn],r[maxn];
int use[maxn],head[maxn],num;
void addedge(int u,int v) {
    edge[l1].to=u;
    edge[l1].next=head[v];
    head[v]=l1++;
}
void dfs(int rt) {
    int i=head[rt];
    l[rt]=++num;
    while(i!=-1) {
        dfs(edge[i].to);
        i=edge[i].next;
    }
    r[rt]=num;
}
void push(int rt) {
    if(la[rt]!=-1) {
        task[rt<<1]=la[rt];
        task[rt<<1|1]=la[rt];
        la[rt<<1]=la[rt];
        la[rt<<1|1]=la[rt];
        la[rt]=-1;
    }
}
int find_set(int x) {
    if(use[x] != x) {
        use[x]=find_set(use[x]);
    }
    return use[x];
}
void build(int l,int r,int rt) {
    task[rt]=-1;
    la[rt]=-1;
    if(l==r) return ;
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
}
void update(int L,int R,int val,int l,int r,int rt) {
    if(L <= l && r <= R) {
        task[rt]=val;
        la[rt]=val;
        return;
    }
    push(rt);
    int m=(l+r)>>1;
    if(L <= m) update(L,R,val,l,m,rt<<1);
    if(R > m) update(L,R,val,m+1,r,rt<<1|1);
}
void query(int L,int R,int l,int r,int rt) {
    if(L <= l && r <= R) {
        printf("%d\n",task[rt]);
        return;
    }
    push(rt);
    int m=(l+r)>>1;
    if(L <= m) query(L,R,l,m,rt<<1);
    if(R > m) query(L,R,m+1,r,rt<<1|1);
}
int main() {
    int T;
    scanf("%d",&T);
    int cas=1;
    while(T--) {
        int n;
        scanf("%d",&n);
        l1=0;
        num=0;
        for(int i=0;i<=n;i++) {
            head[i]=-1;
            use[i]=i;
        }
        int u,v;
        for(int i=1;i<n;i++) {
            scanf("%d%d",&u,&v);
            use[u]=v;
            addedge(u,v);
        }
        int root=find_set(1);
        dfs(root);
        build(1,num,1);
        int m;
        read(m);
        char op[5];
        int a,b;
        printf("Case #%d:\n",cas++);
        for(int i=0;i<m;i++) {
            scanf("%s",op);
            if(op[0]=='C') {
                read(a);
                query(l[a],l[a],1,num,1);
            }
            else {
                read(a),read(b);
                update(l[a],r[a],b,1,num,1);
            }
        }
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值