题意:
给一颗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的更多相关文章

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

  2. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  3. SPOJ QTREE Query on a tree --树链剖分

    题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...

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

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

  6. SPOJ QTREE Query on a tree ——树链剖分 线段树

    [题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...

  7. SPOJ QTREE - Query on a tree 【树链剖分模板】

    题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...

  8. SPOJ QTREE Query on a tree V ——动态点分治

    [题目分析] QTREE4的弱化版本 建立出分治树,每个节点的堆表示到改点的最近白点距离. 然后分治树上一直向上,取min即可. 正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补. ...

  9. SPOJ - QTREE Query on a tree题解

    题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了 ...

随机推荐

  1. 关于JS的数据类型的一些见解

    关于js里的数据类型这块,说下个人对它的一些见地 js中的数据类型可以归类两类, 简单数据类型:string,number,boolean,null,undefined 复杂数据类型:object 其 ...

  2. svn server

    svn server: 1.c:\Program Files\TortoiseSVN\bin>svnserve -d -r C:\Jasper\Repositories2.change the ...

  3. java中的标记接口

    在java 中,RandomAccess和Cloneable .Serializable一样,都是标志性接口,不需要任何实现,只是又来表明其实现类具体有某种特质的,实现了Cloneable表明可以拷贝 ...

  4. Knockout学习笔记之一

    1.  四大关键理念: A. DeclarativeBindings(声明式绑定) Easily associate DOM elements with model data using a conc ...

  5. django template

    一.模板基本元素 1.例子程序 1)urls.py中新增部分 from django.conf.urls import patterns, url, include urlpatterns = pat ...

  6. Mongodb异常关闭重启失败解决

    情况再现,连接mongodb的网站没有关,直接关闭了mongodb的cmd窗口.再次打开mongodb出现失败. 解决办法:网上说是删除 *.lock文件,再进行 --repair ,最后再打开mon ...

  7. iOS开发网络篇—发送json数据给服务器以及多值参数

    iOS开发网络篇—发送json数据给服务器以及多值参数 一.发送JSON数据给服务器 发送JSON数据给服务器的步骤: (1)一定要使用POST请求 (2)设置请求头 (3)设置JSON数据为请求体 ...

  8. BestCoder Round #43

    T1:pog loves szh I(hdu 5264) 题目大意: 给出把AB两个字符串交叉拼起来的结果,求出原串. 题解: 不解释..直接每次+2输出. T2:pog loves szh II(h ...

  9. ASP.NET关于WebPages的一点总结

    相比于早期的ASP,WebPage貌似只是多了一些Razor语法可以直接调用服务器代码,其他的内容HTML.样式CSS以及脚本JavaScript基本都是一样的处理方式 只是说内容HTML里面加入了更 ...

  10. 简单工厂模式(Simple Factory)

    从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一 ...