离散化+权值线段树

题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于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序的更多相关文章

  1. HDU 5692 线段树+dfs序

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  2. hdu 5039 线段树+dfs序

    http://acm.hdu.edu.cn/showproblem.php?pid=5039 给定一棵树,边权为0/1.m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数. 用树形df ...

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

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  4. 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序

    题目大意 ​ Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...

  5. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  6. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  7. 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 ...

  8. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  9. CF620E New Year Tree 线段树 dfs序

    luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...

随机推荐

  1. win10+ubuntu双系统修复ubuntu启动引导

    因为windows是不能引导linux的,而每次win10升级或恢复都会将linux的启动引导覆盖掉,导致无法进入linux, 所以一直就禁止了win10更新.这几天win10出了点小毛病,所以就狠下 ...

  2. 数据结构和算法(Golang实现)(7)简单入门Golang-标准库

    使用标准库 一.避免重复造轮子 官方提供了很多库给我们用,是封装好的轮子,比如包fmt,我们多次使用它来打印数据. 我们可以查看到其里面的实现: package fmt func Println(a ...

  3. .Net Core MVC 基于Cookie进行用户认证

    在打代码之前先说一下思路. 登录的的时候服务端生成加密的字符串(用户名.id.当前时间)并且存入客户端cookie中,服务端的缓存中.对客户端的每次请求进行拦截,解密保存在cookie中的加密字符串. ...

  4. AJ学IOS(55)多线程网络之图片下载框架之SDWebImage

    AJ分享,必须精品 效果: 代码: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsO ...

  5. 关于 System.IO.File.Exists 需要注意的事项

    各位:   .NET Framework 本省在设计的时候,他对于异常没有完全做到抛出,这样可能会有很多意想不到的问题.   比如 你在asp.net 应用程序中判断文件是否存在,这个文件可能是一个共 ...

  6. Python套接字之UDP

    目录 基于UDP的socket 发送消息 接收消息 基于UDP的socket 面向无连接的不可靠数据传输,可以没有服务器端,只不过没有服务器端,发送的数据会被直接丢弃,并不能到达服务器端 发送消息 在 ...

  7. 多线程高并发编程(6) -- Semaphere、Exchanger源码分析

    一.Semaphere 1.概念 一个计数信号量.在概念上,信号量维持一组许可证.如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它.每个release()添加许可证,潜在地释 ...

  8. 下载mp4文件

    实现mp4文件的下载,而不是在线播放 <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  9. selenium 键盘鼠标模拟

    一.键盘模拟常用的键 sendKeys(Keys.BACK_SPACE);  //删除键--Backspace sendKeys(Keys.SPACE);   //空格键 Space sendKeys ...

  10. python 基础篇 类基础与继承

    先来简单解释几个概念 类:一群有着相同属性和函数的对象的集合,这里对应 Python 的 class. 对象:集合中的一个事物,这里对应由 class 生成的某一个 object,比如代码中的 har ...