SPOJ QTREE Query on a tree
题意:
给一颗n个点的树,有两种操作
CHANGE i ti : 把第i条边的权变为ti
QUERY a b : 问点a 到 点b 之间的边的最大权
思路:
树剖处理边权。
由于是边,所以只需要把边权处理到子节点上即可(查询的时候从节点2开始查询,或者把0处理成负无穷)
具体见代码:
const int maxn = + ;
const int maxnode = maxn * ; //线段树部分
int set_value, qL, qR;
int maxv[maxnode]; void update(int o, int L, int R)
{
if (qL <= L && R <= qR)
{
maxv[o] = set_value;
return;
}
int M = L + (R - L) / ;
if (qL <= M) update(lson);
if (qR > M) update(rson);
maxv[o] = max(maxv[o*], maxv[o*+]);
} int query(int o, int L, int R) {
if (qL <= L && R <= qR)
{
return maxv[o];
}
int M = L + (R - L) / ;
int ret = -INF;
if (qL <= M) ret = max(ret, query(lson));
if (qR > M) ret = max(ret, query(rson));
return ret;
} //树链剖分部分:
//
//u为连接的点,w为边权
struct Edge { int u, v, w; };
vector<int> G[maxn];
vector<Edge> e;
//往往是双向边
void add_edge(int u, int v, int w)
{
e.push_back((Edge){u, v, w});
G[u].push_back(v);
G[v].push_back(u);
} struct Node
{
int size, dep, son, top, fa, ti;
//依次表示第i个节点的:
//子节点数量,深度,所在链的顶端,重儿子,dfs序
} t[maxn]; int dfs_clock;//DFS时间序列 void dfs1(int u, int pa, int depth)//第一次DFS,得到size,dep,fa以及son的数据
{
t[u].son = ; //重儿子,为0表示没有重儿子
t[u].size = ; //节点数量
t[u].dep = depth;
t[u].fa = pa;
for (int i = ; i != G[u].size(); ++ i)
{
int v = G[u][i];
if (v == pa) continue;
dfs1(v, u, depth + );
t[u].size += t[v].size;
if (t[v].size > t[t[u].son].size) t[u].son = v;
}
} void dfs2(int u, int pa) // 得到时间戳等数据,u为当前节点,pa为父链顶端节点
{
t[u].ti = ++ dfs_clock; //u这个节点的时间戳是dfs_clock,dfs_clock下标是从1开始的,没有0!
t[u].top = pa; //top是u所在链的顶端
if (t[u].son != ) dfs2(t[u].son, t[u].top); //如果节点有重儿子,那么依旧是以pa为链顶端的一条链
for (int i = ; i != G[u].size(); ++ i)
{
int v = G[u][i];
if (v == t[u].son || v == t[u].fa) continue;//重儿子或者父节点,则跳过
dfs2(v, v);//新的一条链
}
} int n;
int lca(int x, int y)//更新x到y的之间所有的区间
{
int ret = -INF;
while (t[x].top != t[y].top)
{
if (t[t[x].top].dep < t[t[y].top].dep) swap(x,y); //x深 y浅
qL=t[t[x].top].ti;
qR=t[x].ti;
ret = max(ret, query(, , n));
x = t[t[x].top].fa;
}
if (t[x].dep > t[y].dep) swap(x, y);//x是上面一些的节点
if (x != y)
{
qL = t[x].ti + ;
qR = t[y].ti;
ret = max(ret, query(, , n));
}
return ret;
} void init()
{
memset(maxv, , sizeof(maxv));
dfs_clock = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) G[i].clear();
e.clear();
int u, v, w;
for (int i = ; i < n; i++)
{
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
} void solve()
{
dfs1(, , );
dfs2(, ); for (int i = ; i < n; i++)
{
set_value = e[i-].w;
if (t[e[i-].u].dep < t[e[i-].v].dep)
qL = qR = t[e[i-].v].ti;
else
qL = qR = t[e[i-].u].ti;
update(, , n);
}
char op[];
int u, v;
while (true)
{
scanf("%s", op);
if (op[] == 'D') break;
scanf("%d%d", &u, &v);
if (op[] == 'Q')
{
printf("%d\n", lca(u, v));
}
else
{
set_value = v;
if (t[e[u-].u].dep < t[e[u-].v].dep)
qL = qR = t[e[u-].v].ti;
else
qL = qR = t[e[u-].u].ti;
update(, , n);
}
}
printf("\n");
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
init();
solve();
}
return ;
}
SPOJ QTREE Query on a tree的更多相关文章
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- SPOJ QTREE Query on a tree --树链剖分
题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...
- SPOJ QTREE Query on a tree VI
You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are number ...
- SPOJ QTREE Query on a tree V
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are number ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- SPOJ QTREE - Query on a tree 【树链剖分模板】
题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...
- SPOJ QTREE Query on a tree V ——动态点分治
[题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...
- SPOJ - QTREE Query on a tree题解
题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- Scrum Meeting 8-20151210
任务安排 姓名 今日任务 明日任务 困难 董元财 服务器入口更新 服务器发布记录接口 无 胡亚坤 请假(编译攻坚) 聊天界面优化 无 刘猛 请假(编译攻坚) 开新的分支存放服务器端或者,创建的仓库记录 ...
- 学的一点点ps
从C语言的代码中解脱开始学ps,看到色彩鲜明的东西,心里只有那么爽.哈哈.只学习3天,虽然只是一些皮毛,可还是学到了一些以前不知道的东西.让我对ps多了很多兴趣,决定以后要自学更多的ps技能.要给图片 ...
- 基于Jquery、JqueryUI插件编写
刚开始编写jquery插件的时候,只是从网上找个模板看着写,并不理解.刚刚仔细把官网的API看了下,突然觉得豁然开朗了.马上放假了想着应该整理整理不然忘了又. How to create a Jque ...
- javaSE之Object及hashcode等相关知识
object: package javaBasic; public class TestObject { public static void main(String[] args) { // TOD ...
- Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用
#!/usr/bin/Python指定用什么解释器运行脚本以及解释器所在的位置 # -*- coding: utf-8 -*-用来指定文件编码为utf-8的 估计有不少人注意过一些python脚本开头 ...
- 高斯混合模型与EM算法
对于高斯混合模型是干什么的呢?它解决什么样的问题呢?它常用在非监督学习中,意思就是我们的训练样本集合只有数据,没有标签. 它用来解决这样的问题:我们有一堆的训练样本,这些样本可以一共分为K类,用z(i ...
- (转) linux之sort用法
sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式: sort [-bcfMnrtk][源文件][-o 输出文件] 补充说明:sort可针对文本文件的内容,以行为单位来排序. 参 数 ...
- 【ros bug】rplidar.launch is neither a launch file in package...
解决 :cd catkin_ws $ source devel/setup.bash
- C++类的交叉引用
对于C++中,两个类中相互引用对方,当然只能是在指针的基础上,于是我们知道.也就是说在A类的有一个指针引用B类的成员函数或成员对象,而B类中又有一个指针来访问A中的成员函数或对象.这就是C++中类的交 ...
- Ubuntu配置pyethapp
1. 安装系统依赖 apt-get install build-essential automake pkg-config libtool libffi-dev libgmp-dev 2. Clone ...