J - Assign the task HDU - 3974 (线段树 + dfs序)

题意:给一颗树,两种操作,查询 i 结点的颜色,和将i结点和它的子树都染成另一种颜色

题解:dfs序构建线段树,对于x和其子树染色就是 l[x] 和 r[x];

dfs序线段树板子

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<list>
#include<math.h>
#include<vector>
#include<stack>
#include<string>
#include<stdio.h>

using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;

vector<int>vec[MAXN];
int cnt[MAXN],l[MAXN],r[MAXN],vis[MAXN];
int st[MAXN << 2];
void init() {
    memset(l,-1,sizeof l);
    memset(r, -1 ,sizeof r);
    memset(cnt, 0, sizeof cnt);
    memset(vis, 0, sizeof vis);
}

void dfs(int x,int &pos) {
    l[x] = pos ++;
    for(int i = 0; i < vec[x].size(); i++) {
        dfs(vec[x][i],pos);
    }
    r[x] = pos++;
}
void build(int o,int l,int r) {
    st[o] = -1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(o << 1, l , mid);
    build(o << 1 | 1, mid + 1, r);
}
void pushdown(int o) {
    if(st[o] != -1) {
        st[o << 1] = st[o];
        st[o << 1 | 1 ] = st[o];
        st[o] = -1;
    }
}
int query(int o,int l,int r,int x) {
    if(l == r) return st[o];
    pushdown(o);
    int mid = (l + r) >> 1;
    if(x <= mid) query(o << 1, l, mid, x);
    else query(o << 1 | 1, mid + 1, r, x);
}
void update(int o,int l,int r,int ql,int qr,int y) {
    if(ql <= l && r  <= qr) {
        st[o] = y;
        return;
    }
    pushdown(o);
    int mid = (l + r) >> 1;
    if(ql <= mid) update(o << 1, l, mid, ql, qr, y);
    if(qr >= mid + 1) update(o << 1 | 1, mid + 1, r, ql, qr, y);
}
int main() {
    int t, _ = 1;
    scanf("%d", &t);
    while (t--) {
        init();
        printf("Case #%d:\n", _++);
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            vec[i].clear();
        build(1, 1, 2 * n);
        int u, v;
        for (int i = 1; i < n; i++) {
            scanf("%d %d", &u, &v);
            vec[v].push_back(u);
            cnt[u]++;
        }
        int pos = 1;
        for (int i = 1; i <= n; i++) {
            if (cnt[i] == 0) {
                dfs(i,pos);
                break;
            }
        }
//        for(int i = 1;i<=n;i++)
//            printf("%d %d %d\n",i,l[i],r[i]);

        int m;
        scanf("%d",&m);
        while (m--) {
            char s[5];
            int x,y;
            scanf("%s",s);
            if(s[0] == ‘C‘) {
                scanf("%d",&x);
                printf("%d\n",query(1,1,2 * n,l[x]));
            } else {
                scanf("%d %d",&x,&y);
                update(1, 1, 2 * n, l[x],r[x], y);
            }
        }
    }
}

/*

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

 */

原文地址:https://www.cnblogs.com/smallhester/p/11334761.html

时间: 2025-01-20 00:43:29

J - Assign the task HDU - 3974 (线段树 + dfs序)的相关文章

HDU 5692 线段树+dfs序

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1779    Accepted Submission(s): 427 Problem Description 百度科技园内有n 个零食机,零食机之间通过n−1 条路相互连通.每个零食机都有一个值v ,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v

J - Assign the task - hdu 3974(多操作混合区间更新)线段树

题意:有四种操作 1,  区间 [l, r] 的值都加上 C 2,  区间 [l, r] 的值都乘上 C 3,  区间 [l, r] 的值都变为C 4,  求区间 [l, r]所有数的p次方的和 分析:是比较麻烦的区间操作,设计四种操作,更新的时候无法更新到底部,不过仔细思考可以想到这都是对区间进行的操作,所以会造成一部分的区间值相等,所以只需要更新到相等区间部分就行了,而且注意有第三种操作的时候,第二和第一种操作可以去掉,操作的优先性是3>2>1,. WA了一次,因为操作三进行的的时候没有把

hdu 3974 线段树 将树弄到区间上

Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1647    Accepted Submission(s): 753 Problem Description There is a company that has N employees(numbered from 1 to N),every emplo

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

Codeforces 384E 线段树+dfs序

题目链接:点击打开链接 题意: 给定n个点,m个询问的无向树(1为根) 下面n个数表示每个点的权值 下面n-1行给出树 操作1:x点权值+v, x的第 i & 1 的儿子-v, 第 !(i&1) 的儿子+v 操作2:询问x点权值 dfs把树转成序列 根据深度把点分成2组 分别用线段树维护.. 然后Y一下 #include<stdio.h> #include<string.h> #include<iostream> #include<algorith

hdu 3974 Assign the task 线段树 DFS序

给你一棵树,每次修改一个子树的所有值,然后单点查询. 按照DFS序把节点排列(即在DFS中出现的先后次序),同一个子树在序列中连续. 1 #include <cstdio> 2 using namespace std; 3 typedef long long ll; 4 int n,q,T,Tc,cnt,sum; 5 int col[210000],lzy[210000],sta[51000],fin[51000]; 6 int nxt[51000],to[51000],head[51000]

HDU 3974 线段树(将树映射到区间)

第一次写将树映射到区间的线段树... 线段树部分很简单 主要是将原有的关系树根据BOSS关系从新编号 以便把每个BOSS所带领的员工全部压入一个连续区间内 然后记录每个BOSS的起始编号和他的最后一名的员工的编号 然后用线段树成端更新,单点查找即可 #include "stdio.h" #include "string.h" struct node { int l,r,val,lazy; }data[200010]; struct Edge { int to,nex

hdu 3974, 线段树

题意: 有一个公司,有n个人: 这些人之间的关系是一棵树: 即:有的人是老板,有的人是员工,有的人既是老板,又是员工: 然后公司随时都会安排一些工作给他们做: 每次安排至安排一个人,但是他的下属会和他一起做: 题目就是查询当前这个人在做什么工作: 理解: 这个题的题意好理解,读几遍就知道了 但是对于已知的关系: 即:画出的公司员工之间的那棵树: 我是在无法联想到线段树: 之前还想怎么减小时间复杂度,然后暴力解决: 结果肯定是不行的: 所以只有向线段树想: 于是发现: 在分配了任务之后: 只有当前