Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 7268   Accepted: 1969

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source

【思路】

树链剖分,线段树。

又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。

线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。

【代码】

 #include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = +;
const int INF = 1e9; struct Node { int l,r,mx,mn,f;
}T[N<<];
struct Edge {
int u,v,w;
Edge(int u=,int v=,int w=) :u(u),v(v),w(w) {};
};
int n,q,z,d[N][];
vector<Edge> es;
vector<int> g[N]; void adde(int u,int v,int w) {
es.push_back(Edge(u,v,w));
int m=es.size();
g[u].push_back(m-);
}
//INIT
int top[N],son[N],dep[N],fa[N],siz[N],w[N];
void dfs1(int u) {
son[u]=; siz[u]=;
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v; //
if(v!=fa[u]) {
fa[v]=u , dep[v]=dep[u]+;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp) {
top[u]=tp; w[u]=++z;
if(son[u]) dfs2(son[u],tp);
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v;
if(v!=fa[u] && v!=son[u]) dfs2(v,v);
}
}
//SEGMENT TREE
//标记 该结点已被作用而子结点仍未作用
//pushdown 作用于访问节点 即只要访问就pushdown
void pushdown(int u) { //下传标记 同时作用于子结点
if(T[u].f && T[u].l<T[u].r) {
int lc=u<<,rc=lc|;
T[u].f=;
T[lc].f^= ,T[rc].f^=;
int t;
t=T[lc].mn,T[lc].mn=-T[lc].mx,T[lc].mx=-t;
t=T[rc].mn,T[rc].mn=-T[rc].mx,T[rc].mx=-t;
}
}
void maintain(int u) {
T[u].mx=max(T[u<<].mx,T[u<<|].mx);
T[u].mn=min(T[u<<].mn,T[u<<|].mn);
}
void build(int u,int L,int R) {
T[u].l=L,T[u].r=R;
T[u].mn=INF , T[u].mx=-INF , T[u].f=;
if(L==R) return ; //
int M=(L+R)>>;
build(u<<,L,M) , build(u<<|,M+,R);
}
void change(int u,int r,int x) {
pushdown(u); //
if(T[u].l==T[u].r) T[u].mn=T[u].mx=x;
else {
int M=(T[u].l+T[u].r)>>; //
if(r<=M) change(u<<,r,x);
else change(u<<|,r,x);
maintain(u);
}
}
void Negate(int u,int L,int R) {
pushdown(u);
if(L<=T[u].l && T[u].r<=R) {//打标记 同时作用于当前结点
T[u].f=;
int t; t=T[u].mn,T[u].mn=-T[u].mx,T[u].mx=-t; //
}
else {
int M=(T[u].l+T[u].r)>>;
if(L<=M) Negate(u<<,L,R);
if(M<R) Negate(u<<|,L,R);
maintain(u);
}
}
int query(int u,int L,int R) {
pushdown(u);
if(L<=T[u].l && T[u].r<=R) return T[u].mx;
else {
int M=(T[u].l+T[u].r)>>;
int ans=-INF;
if(L<=M) ans=max(ans,query(u<<,L,R));
if(M<R) ans=max(ans,query(u<<|,L,R));
return ans;
}
} //树链剖分
void modify(int u,int v) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
Negate(,w[top[u]],w[u]);
u=fa[top[u]];
}
if(u==v) return ;
if(dep[u]>dep[v]) swap(u,v);
Negate(,w[son[u]],w[v]); //
}
int query(int u,int v) {
int mx=-INF;
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
mx=max(mx,query(,w[top[u]],w[u]));
u=fa[top[u]];
}
if(u==v) return mx;
if(dep[u]>dep[v]) swap(u,v);
mx=max(mx,query(,w[son[u]],w[v]));
return mx;
} void read(int& x) {
char c=getchar();
while(!isdigit(c)) c=getchar();
x=;
while(isdigit(c))
x=x*+c-'' , c=getchar();
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
int T; read(T);
while(T--) {
read(n);
z=; es.clear();
FOR(i,,n) g[i].clear();
int u,v,c;
FOR(i,,n-) {
read(u),read(v),read(c);
d[i][]=u,d[i][]=v,d[i][]=c;
adde(u,v,c),adde(v,u,c);
}
dfs1(),dfs2(,);
build(,,z);
FOR(i,,n-) {
if(dep[d[i][]]<dep[d[i][]]) swap(d[i][],d[i][]);
change(,w[d[i][]],d[i][]);
}
char s[];
while(scanf("%s",s)== && s[]!='D') {
read(u),read(v);
if(s[]=='C') change(,w[d[u][]],v);
else if(s[]=='N') modify(u,v);
else printf("%d\n",query(u,v));
}
}
return ;
}

poj 3237 Tree(树链剖分,线段树)的更多相关文章

  1. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  2. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  3. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  4. POJ3237 Tree 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...

  5. 【CF725G】Messages on a Tree 树链剖分+线段树

    [CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...

  6. Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  7. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  8. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  9. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  10. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

随机推荐

  1. APUE学习笔记-一些准备

    从开始看APUE已经有快一个星期了,由于正好赶上这几天清明节放假,难得有了三天空闲假期可以不受打扰的学习APUE,现在已经看完前六章了,里面的大部分例程也都亲自编写,调试过了.但总觉得这样学过就忘,因 ...

  2. 收藏一个匹配html内容的文章

    http://blog.csdn.net/donglynn/article/details/35788879

  3. TDirectory.Copy复制文件

    描述:复制文件夹以及文件夹下的内容 procedure Copy(const SourceDirName, DestDirName: string) 参数一:源文件夹 参数二:目标文件夹 所在单元:S ...

  4. Python的简介以及安装和第一个程序以及用法

    Python的简介: 1.Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.自从20世纪90年代初Python语言诞生至今,它逐渐被广泛应用于处理系统管理任务和Web编程.Pytho ...

  5. pyqt中使用matplotlib绘制动态曲线

    一.项目背景: 看了matplotlib for python developers这本书,基本掌握了在pyqt中显示曲线的做法,于是自己写一个. 二.需求描述: 1)X轴显示时间点,显示长度为1分钟 ...

  6. NDK_ROOT找不到的解决方法 MACOS

    只要在Eclipse上进行配置就行了,看图说话  

  7. bzoj2427: [HAOI2010]软件安装

    Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...

  8. UISearchBar -- 备忘

    搜索功能的备忘 UISearchBar UISearchBar是一个搜索栏,继承自UIView,也是常用的控件之一,所以特别写一篇备忘方便以后做工具文章. 例子: let searchBar = UI ...

  9. iOS --- 取整数

    Objective-C拓展了C,自然很多用法是和C一致的.比如浮点数转化成整数,就有以下四种情况. 1.简单粗暴,直接转化 float f = 1.5; int a; a = (int)f; NSLo ...

  10. 10 个 jQuery 的无限滚动的插件:

    很多社交网站都使用了一些新技术来提高用户体验,而无限滚动的翻页技术就是其中一项,当你页面滑到列表底部时候无需点击就自动加载更多的内容. 下面为你推荐 10 个 jQuery 的无限滚动的插件: 1.  ...