S - Query on a tree HDU - 3804 线段树+dfs序
题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度。
这个题目和之前写的那个给你一棵树询问这棵树的这个节点到根节点之间的节点权重相乘小于等于k的对数非常像。
之前是不是就是放进去弹出来的操作,这个也是一样,之前用的是离散化逆序对的思想来求,这个开始没有想到。
然后自己写了一个很暴力的线段树,线段树要是没有一个连续的区间是有很高复杂度的。
所以要想办法把这个转化成一个连续的区间,这个和上面一样通过逆序对的思想也可以转化成一个连续的区间。
首先把这个数进行离散化,然后建树,最后就是dfs序+线段树。
我这么写要注意初始化,因为可能是在根节点1 的时候询问,这个就不会在后面被考虑到,所以输出这个数组要初始化为-1
然后我出了一个在query这里,id<<1,忘记了 |1,
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <math.h>
#include <iostream>
#include <algorithm>
#define debug(n) printf("%d\n",n)
using namespace std;
typedef long long ll;
const int maxn = 1e5 + ;
int n, out[maxn], b[maxn], len;
struct node {
int v;
int w;
node(int v = , int w = ) :v(v), w(w) {}
};
struct edge {
int w;
int id;
edge(int w = , int id = ) :w(w), id(id) {}
};
vector<node>G[maxn];
vector<edge>e[maxn];
int sum[maxn * ], maxx[maxn * ]; void push_up(int id) {
sum[id] = sum[id << ] + sum[id << | ];
maxx[id] = max(maxx[id << ], maxx[id << | ]);
// printf("maxx[%d]=%d\n",id,maxx[id]);
} void update(int id, int l, int r, int pos, int val) {
// printf("id=%d l=%d r=%d pos=%d val=%d\n", id, l, r, pos, val);
if (l == r) {
sum[id] += val;
if (sum[id]) maxx[id] = l;
else maxx[id] = ;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , l, mid, pos, val);
else update(id << | , mid + , r, pos, val);
push_up(id);
} int query(int id, int l, int r, int x, int y) {
if (x <= l && y >= r) return maxx[id];
int mid = (l + r) >> ;
int ans = ;
// printf("id=%d x=%d y=%d\n",id,x,y);
if (x <= mid) ans = max(ans, query(id << , l, mid, x, y));
// cout<<x<<' '<<y<<endl;
if (y > mid) ans = max(ans, query(id << | , mid + , r, x, y));
// printf("!!id=%d ans=%d x=%intd y=%intd mid=%d\n", id, ans,x,y,mid); return ans;
} void dfs(int u, int pre) {
for (int i = ; i < G[u].size(); i++) {
node now = G[u][i];
if (now.v == pre) continue;
int t = lower_bound(b + , b + + len, now.w) - b;
update(, , len, t, );
// printf("www now.v=%d t=%d\n",now.v,t);
for (int j = ; j < e[now.v].size(); j++) {
edge x = e[now.v][j];
int t1 = upper_bound(b + , b + + len, x.w) - b - ;
int ans = ;
if (t1 <= ) {
// cout<<x.id<<'!'<<endl;
out[x.id] = -;
}
else {
// printf("t1=%d\n",t1);
ans = query(, , len, , t1);
if (ans == ) out[x.id] = -;
else out[x.id] = b[ans];
}
}
dfs(now.v, u);
update(, , len, t, -);
// printf("qqq now.v=%d t=%d\n",now.v,t);
}
} int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) G[i].clear(), e[i].clear();
for (int i = ; i < n; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back(node(v, w));
G[v].push_back(node(u, w));
b[i] = w;
}
sort(b + , b + n);
len = unique(b + , b + n) - b - ;
memset(sum, , sizeof(sum));
memset(maxx, , sizeof(maxx));
int q;
scanf("%d", &q);
for (int i = ; i <= q; i++) {
int u, w;
scanf("%d%d", &u, &w);
e[u].push_back(edge(w, i));
}
memset(out, -, sizeof(out));
dfs(, -);
for (int i = ; i <= q; i++) printf("%d\n", out[i]);
}
return ;
}
/*
4
5
1 2 2
1 3 4
2 4 6
2 5 8
2
3 4
2 2
*/
线段树+dfs序
S - Query on a tree HDU - 3804 线段树+dfs序的更多相关文章
- HDU 5692 线段树+dfs序
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- hdu 5039 线段树+dfs序
http://acm.hdu.edu.cn/showproblem.php?pid=5039 给定一棵树,边权为0/1.m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数. 用树形df ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- HDU 6191 Query on A Tree(可持久化Trie+DFS序)
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- CF620E New Year Tree 线段树 dfs序
luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...
随机推荐
- 差分数组&&定义&&使用方法&&与线段树的区别
**1.定义**对于一个有n个元素的数组a[n],我们令a[i]-a[i-1]=d[i],且d[1]=a[1]-0=a[1];那么我们将d[i]称为**差分数组**---即记录数组中的每项元素与前一项 ...
- Linux c++ vim环境搭建系列(3)——Ubuntu18.04.4编译安装youcompleteme
3. youcompleteme编译安装 参考网址: https://github.com/ycm-core/YouCompleteMe#linux-64-bit 建议不要用这个博客的方法: http ...
- alg-查找只出现一次的数
//只有2个数出现1次,其余的数都出现2次 class Solution { public: vector<int> singleNumber(const vector<int> ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- 【图解】你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了
每日一句英语学习,每天进步一点点: 前言 前一篇「硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题」得到了很多读者的认可,在此特别感谢你们的认可,大家都暖暖的. 来了,今 ...
- 资料整理:python自动化测试——操作测试对象
文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:爱吃米饭的猪 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自 ...
- Feature list, Standard and Test plan for BETA Release 12/22/2015
===================BETA RELEASE FEATRURE LIST==================== 1. Log in and account manager for ...
- Jmeter发送jdbc请求进行大批量造数
创建批量造数脚本,一个简单的结构如下图所示, 1.线程组(10个线程重复运行2次,相当于造20个数) 2.用户定义变量(这是全局变量,用于后面随机筛选用) 3.数据库连接配置 4.计数器(用于主键递增 ...
- Labyrinth 树的直径加DFS
The northern part of the Pyramid contains a very large and complicated labyrinth. The labyrinth is d ...
- F - Robot Motion 栈加BFS
A robot has been programmed to follow the instructions in its path. Instructions for the next direct ...