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.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...
随机推荐
- C语言复杂声明
C语言复杂声明 First step int *f(); /* f:是一个函数,它返回一个指向int类型的指针*/ int (*pf)(); /* pf:是一个指向函数的指针,该函数返回一个int类型 ...
- C语言语法之关键字
注:该内容整理自以下链接. http://www.cnblogs.com/yezhenhan/archive/2011/10/16/2214420.html 由ANSI标准定义的C语言关键字共32个: ...
- List怎么遍历删除元素
public static void main(String[] args) { List<String> list = new ArrayList<String>(); ...
- Hibernate疑问
官方User_guide中,3.2节 JPA Bootstrapping 第一段最后一句话, The standardized approach has some limitations in cer ...
- cube定时器延时不准确原因
昨天晚上测试32cube配置好定时器,以1ms为一次中断,然后在程序中做了一个1s的延时,结果发现实际延时5s左右,百思不得其解,仔细查看cube配置也没问题.最后我打开生成工程文件夹里面的ioc文件 ...
- 关于JAVA EE项目在WEB-INF目录下的jsp页面如何访问WebRoot中的CSS和JS文件
找了这么久资料,总算解决了 感谢博客园:http://www.cnblogs.com/xsht/p/5275081.html 感谢百度:http://zhidao.baidu.com/link?url ...
- Django1.9开发博客(6)- 模板继承
模板继承就是网站的多个页面可以共享同一个页面布局或者是页面的某几个部分的内容.通过这种方式你就需要在每个页面复制粘贴同样的代码了. 如果你想改变页面某个公共部分,你不需要每个页面的去修改,只需要修改一 ...
- 【转】Mysql中varchar存放中文与英文所占字节异同
本文转自Ruby china, 原文地址:https://ruby-china.org/topics/24920 一.关于UTF-8 UTF-8 Unicode Transformation Form ...
- [hadoop] 一些基础概念
一.云的概念 1.云计算的概念 随时 随地 使用任何设备 获得任何服务 2.趋势 )资料开始回归集中处理(存储大量资料) 随时存取 降低遗失风险 减少传输成本 促进团队协作 )网页变为预设开发平台(网 ...
- C#高级进阶--重写函数
这里要说一下,重写是继承时发生,在子类中重新定义父类中的方法.例如:基类方法声明为virtual方法,派生类中使用override声明此方法的重写. 基类中的访问修饰符在子类中是不能被修改的.比如说基 ...