【hdu4366】dfs序线段树

  1 #include <bits/stdc++.h>
  2 #define ll long long
  3 #define lson l, m, rt<<1
  4 #define rson m+1, r, rt<<1|1
  5 using namespace std;
  6 const int N = 5e4+5;
  7
  8 vector<int> ve[N];
  9 int b[N], c[N], tot;
 10 int l[N], r[N], ans[N];
 11 void dfs(int fa, int x){
 12     tot++;
 13     l[x] = tot;
 14     for(int i = 0; i < ve[x].size(); i++){
 15         int y = ve[x][i];
 16         if(y == fa) continue ;
 17         dfs(x, y);
 18     }
 19     r[x] = tot;
 20 }
 21
 22 struct Node{
 23     int b, pos;
 24     Node(){}
 25     Node(int b, int pos): b(b), pos(pos){}
 26     bool operator <(const Node& a) const{
 27         return b < a.b;
 28     }
 29 };
 30 Node T[N<<2];
 31
 32 void pushup(int rt){
 33     T[rt] = max(T[rt<<1], T[rt<<1|1]);
 34 }
 35 void build(int l, int r, int rt){
 36     T[rt].b = T[rt].pos = -1;
 37     if(l == r) return ;
 38     int m = l+r >> 1;
 39     build(lson);
 40     build(rson);
 41 }
 42 void update(int pos, Node x, int l, int r, int rt){
 43     if(pos == l&&r == pos){
 44         T[rt] = x;
 45         return ;
 46     }
 47     int m = l+r >> 1;
 48     if(pos <= m) update(pos, x, lson);
 49     else update(pos, x, rson);
 50     pushup(rt);
 51 }
 52 Node query(int L, int R, int l, int r, int rt){
 53     if(L <= l&&r <= R)
 54         return T[rt];
 55     int m = l+r >> 1;
 56     Node ret = Node(-1, -1);
 57     if(L <= m) ret = max(ret, query(L, R, lson));
 58     if(R > m) ret = max(ret, query(L, R, rson));
 59     return ret;
 60 }
 61
 62 struct p{
 63     int b, c, id, kth;
 64     p(){}
 65     p(int b, int c, int id, int kth):b(b), c(c), id(id), kth(kth){}
 66     bool operator < (const p& a) const{
 67         return c != a.c? c > a.c: kth < a.kth;
 68     }
 69 };
 70 p pp[N];
 71
 72 int main(){
 73     int t; scanf("%d", &t);
 74     while(t--){
 75         int n, m, x;
 76         scanf("%d%d", &n, &m);
 77         for(int i = 0; i < n; i++) ve[i].clear();
 78         b[0] = c[0] = -1;
 79         for(int i = 1; i < n; i++){
 80             scanf("%d%d%d", &x, b+i, c+i);
 81             ve[x].push_back(i);
 82         }
 83
 84         tot = 0;
 85         dfs(-1, 0);
 86         for(int i = 0; i < n; i++)
 87             pp[i] = p(b[i], c[i], i, l[i]);
 88         sort(pp+1, pp+n);
 89         build(1, n, 1);
 90         for(int i = 1; i < n; i++){
 91             int j = pp[i].id;
 92             int L = l[j]+1, R = r[j];
 93             if(L > R) ans[j] = -1;
 94             else
 95                 ans[j] = query(L, R, 1, tot, 1).pos;
 96             update(l[j], Node(pp[i].b, pp[i].id), 1, tot, 1);
 97         }
 98         while(m--){
 99             scanf("%d", &x);
100             printf("%d\n", ans[x]);
101         }
102     }
103     return 0;
104 }

时间: 2024-12-29 06:53:27

【hdu4366】dfs序线段树的相关文章

POJ 3321 DFS序+线段树

单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include <cstdio> 6: #include <cstring> 7: #include <cctype> 8: #include <algorithm> 9: #include <vector> 10: #include <iostream> 1

codevs1228 (dfs序+线段树)

总结: 第一次遇到dfs序的问题,对于一颗树,记录节点 i 开始搜索的序号 Left[i] 和结束搜索的序号 Righti[i],那么序号在 Left[i] ~ Right[i] 之间的都是节点 i 子树上的节点. 并且此序号与线段树中 L~R 区间对应,在纸上模拟了几遍确实如此,但暂时还未理解为何对应. 此题就是dfs序+线段树的裸题 代码: #include<iostream> #include<vector> #include<cstring> #include&

[BZOJ 3306]树(dfs序+线段树+倍增)

Description 给定一棵大小为 n 的有根点权树,支持以下操作: • 换根 • 修改点权 • 查询子树最小值 Solution 单点修改子树查询的话可以想到用dfs序+线段树来处理,换根的处理画一画图应该可以明白: 如果查询的x是当前的根rt,直接返回整棵树的min 如果rt在x的子树中,用倍增的方法找到离x最近的rt的祖先t,整棵树除t的子树以外的部分就是x当前根下的子树 如果rt不在x的子树中,查询x原来的子树的min值 #include<iostream> #include<

Educational Codeforces Round 6 E dfs序+线段树

题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili上电子科技大学发的视频学习的 将一颗树通过dfs编号的方式 使每个点的子树的编号连在一起作为相连的区间 就可以配合线段树搞子树 因为以前好像听说过 线段树可以解决一种区间修改和查询区间中不同的xx个数...所以一下子就想到了... 但是我不会写线段树..只会最简单的单点修改区间查询...不会用延迟标

【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景.所有场景和选择支构成树状结构:开始游戏时在根节点(共通线)

【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\),问你答案是多少. \(n\leq {10}^5,k\leq {10}^9\) 题解 设\(l\)为这棵树的叶子个数,显然当\(k>\)树的深度时答案都是\(l\). 下面要证明:答案是\(O(l+\frac{n-l}{k})\)的. 我们从下往上贪心,每次选择一个未被覆盖的深度最深的点,覆盖这个点网

codeforces 343D Water Tree 树链剖分 dfs序 线段树 set

题目链接 这道题主要是要考虑到同一棵子树中dfs序是连续的 然后我就直接上树剖了... 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=600005; 4 5 struct Node 6 { 7 int l,r; 8 int value; 9 void init() 10 { 11 l=r=value=0; 12 } 13 }tree[4*MAXN]; 14 vector<int>nei[MAXN]

Manthan, Codefest 16(G. Yash And Trees(dfs序+线段树))

题目链接:点击打开链接 题意:给你一棵树, 根结点为1, q组操作, 每组操作有两种, 一种是对一个结点的所有子树结点的值全部+1, 另一种是查询一个结点的子树结点上值%m的余数为素数的个数. 思路:对于第一个操作, 我们可以想到用dfs序给树重新标号, 使得一个结点的子树结点为相邻的一条线段, 这样,就可以很容易的用线段树进行处理了.  对于第二个操作, 为了维护一个区间内的值, 我们可以用bitset作为结点信息.  我们可以开一个m位的bitset, 对于每个位, 1表示这个数在此区间中,

cdoj 574 High-level ancients dfs序+线段树

High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/574 Description Love8909 is keen on the history of Kingdom ACM. He admires the heroic undertakings of Lxhgww and Haibo. Inspired by those sagas, L

HDU 4366 Successor( DFS序+ 线段树 )

Successor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2631    Accepted Submission(s): 634 Problem Description Sean owns a company and he is the BOSS.The other Staff has one Superior.every st