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.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- Android Studio 简单设置
转自:http://ask.android-studio.org/?/article/14 界面设置 默认的 Android Studio 为灰色界面,可以选择使用炫酷的黑色界面.Settings - ...
- C++ do{...}while(0)的好处
在开源软件里面经常可以看到这样的写法. #define X(a) do { f1(a); f2(a); } while(0) 1. 主要作用是放在宏定义里面,避免宏带来的语法问题. 比如 #defin ...
- FTPS链接服务器
一.首先登录ftp服务器:命令行 lftp user@ip 上传:put 下载: get 二. 关于FTP传输模式与传输的方式 众所周知,FTP传输有两种工作模式,Active Mode和Pass ...
- MFC编程入门之十二(对话框:非模态对话框的创建及显示)
上一节讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 非模态对话框显示后,程序其他窗口仍然能正常运行,可以响应用户输入,还可以相互切换.上一讲中创建的Tip模态对话框 ...
- 转!!log4j基础
log4j组件介绍 Log4j主要有三个组件: Logger:负责供客户端代码调用,执行debug(Object msg).info(Object msg).warn(Object msg).erro ...
- Django1.9开发博客(6)- 模板继承
模板继承就是网站的多个页面可以共享同一个页面布局或者是页面的某几个部分的内容.通过这种方式你就需要在每个页面复制粘贴同样的代码了. 如果你想改变页面某个公共部分,你不需要每个页面的去修改,只需要修改一 ...
- meta name="viewport" content="width=device-width,initial-scale=1.0" 解释
<meta name="viewport" content="width=device-width,initial-scale=1.0"> c ...
- python语言的优点和缺点
python作为一门高级编程语言,它的诞生虽然很偶然,但是它得到程序员的喜爱却是必然之路. 龟叔给Python的定位是"优雅"."明确"."简单&qu ...
- 使用Maven构建RichFaces 4.x项目
使用Maven构建RichFaces 4.x项目 目录 开始之前 第一步 - 创建Maven项目 第二布 - 添加依赖文件 第三步 - 配置RichFaces 第四步 - 创建显示页面 开始之前 本文 ...
- java发送 get请求
package com.java.base; import java.io.BufferedReader; import java.io.InputStreamReader; import java. ...