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],ind[51000];
  7 void build(int k,int l,int r)
  8 {
  9     lzy[k] = -1;
 10     if (l == r)
 11     {
 12         col[k] = -1;
 13         return;
 14     }
 15     int mid = l + r >> 1;
 16     build(k << 1,l,mid);
 17     build(k << 1 | 1,mid + 1,r);
 18 }
 19 void down(int k,int l,int r)
 20 {
 21     if (l == r)
 22     {
 23         lzy[k] = -1;
 24         return;
 25     }
 26     int mid = l + r >> 1;
 27     col[k << 1] = lzy[k];
 28     col[k << 1 | 1] = lzy[k];
 29     lzy[k << 1] = lzy[k];
 30     lzy[k << 1 | 1] = lzy[k];
 31     lzy[k] = -1;
 32 }
 33 void change(int k,int l,int r,int x,int y,int c)
 34 {
 35     if (x <= l && r <= y)
 36     {
 37         lzy[k] = c;
 38         col[k] = c;
 39         return;
 40     }
 41     if (lzy[k] != -1) down(k,l,r);
 42     int mid = l + r >> 1;
 43     if (x <= mid) change(k << 1,l,mid,x,y,c);
 44     if (y >= mid + 1) change(k << 1 | 1,mid + 1,r,x,y,c);
 45 }
 46 int query(int k,int l,int r,int x)
 47 {
 48     if (l == r) return col[k];
 49     if (lzy[k] != -1) down(k,l,r);
 50     int mid = l + r >> 1;
 51     if (x <= mid) return query(k << 1,l,mid,x);
 52     if (x >= mid + 1) return query(k << 1 | 1,mid + 1,r,x);
 53 }
 54 void add(int x,int y)
 55 {
 56     nxt[++cnt] = head[x];
 57     to[cnt] = y;
 58     head[x] = cnt;
 59 }
 60 void dfs(int x)
 61 {
 62     sta[x] = ++sum;
 63     for (int i = head[x];i;i = nxt[i])
 64         dfs(to[i]);
 65     fin[x] = sum;
 66 }
 67 int main()
 68 {
 69     for (scanf("%d",&T);T;T--)
 70     {
 71         printf("Case #%d:\n",++Tc);
 72         scanf("%d",&n);
 73         int tx,ty;
 74         for (int i = 1;i <= n - 1;i++)
 75         {
 76             scanf("%d%d",&tx,&ty);
 77             add(ty,tx);
 78             ind[tx]++;
 79         }
 80         for (int i = 1;i <= n;i++)
 81             if (ind[i] == 0)
 82             {
 83                 dfs(i);
 84                 break;
 85             }
 86         build(1,1,n);
 87         scanf("%d",&q);
 88         char str[10];
 89         for (int i = 1;i <= q;i++)
 90         {
 91             scanf("%s",str);
 92             if (str[0] == ‘T‘)
 93             {
 94                 scanf("%d%d",&tx,&ty);
 95                 change(1,1,n,sta[tx],fin[tx],ty);
 96             }else
 97             {
 98                 scanf("%d",&tx);
 99                 printf("%d\n",query(1,1,n,sta[tx]));
100             }
101         }
102         for (int i = 1;i <= n;i++)
103             ind[i] = head[i] = 0;
104         for (int i = 1;i <= cnt;i++)
105             nxt[i] = 0;
106         cnt = sum = 0;
107     }
108     return 0;
109 }

原文地址:https://www.cnblogs.com/iat14/p/12189685.html

时间: 2024-10-01 04:18:30

hdu 3974 Assign the task 线段树 DFS序的相关文章

HDU 3974 Assign the task(线段树)

描述There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordin

线段树+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 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 (线段树 + dfs序)

题意:给一颗树,两种操作,查询 i 结点的颜色,和将i结点和它的子树都染成另一种颜色 题解:dfs序构建线段树,对于x和其子树染色就是 l[x] 和 r[x]; dfs序线段树板子 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<queue>

HDU 3974 Assign the task 并查集/图论/线段树

Assign the task Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3974 Description There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the l

hdu 3974 Assign the task(线段树)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3974 题意:给定一棵树,50000个节点,50000个操作,C x表示查询x节点的值,T x y表示更新x节点及其子节点的值为y 大致把边存一下那一棵树来举例子 2 3 5 4 1 例如像这样的一棵树,可以将2->1,3->2,4->3,1->4,5->5按照dfs序来编号,然后用线段树进行区间修改,稍微想一想 应该都会了. #include <iostream> #

HDU - 3974 Assign the task (线段树区间修改+构建模型)

https://cn.vjudge.net/problem/HDU-3974 题意 有一棵树,给一个结点分配任务时,其子树的所有结点都能接受到此任务.有两个操作,C x表示查询x结点此时任务编号,T x y表示给x结点分配编号为y的任务. 分析 题目读起来就很有区间修改的味道,将一个区间变为一个值.问题在于怎么把这棵树对应到区间上. 对于一个结点,其控制的范围是它的子树,对应区间范围可以看作是以dfs序表示的区间.好像有点绕..就是给每个结点再对应一个dfs序,然后在dfs时把这个点控制的子树看