Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 2825   Accepted: 769

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 ab 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

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

Sample Output

1
3

Source

POJ Monthly--2007.06.03, Lei, Tao

树链剖分+线段树实现

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013/8/17 4:04:42
  4 File Name     :F:\2013ACM练习\专题学习\数链剖分\POJ3237Tree.cpp
  5 ************************************************ */
  6
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20
 21 const int MAXN = 100010;
 22 struct Edge
 23 {
 24     int to,next;
 25 }edge[MAXN*2];
 26 int head[MAXN],tot;
 27 int top[MAXN];//top[v]表示v所在的重链的顶端节点
 28 int fa[MAXN]; //父亲节点
 29 int deep[MAXN];//深度
 30 int num[MAXN];//num[v]表示以v为根的子树的节点数
 31 int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
 32 int fp[MAXN];//和p数组相反
 33 int son[MAXN];//重儿子
 34 int pos;
 35 void init()
 36 {
 37     tot = 0;
 38     memset(head,-1,sizeof(head));
 39     pos = 0;
 40     memset(son,-1,sizeof(son));
 41 }
 42 void addedge(int u,int v)
 43 {
 44     edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
 45 }
 46 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son
 47 {
 48     deep[u] = d;
 49     fa[u] = pre;
 50     num[u] = 1;
 51     for(int i = head[u];i != -1; i = edge[i].next)
 52     {
 53         int v = edge[i].to;
 54         if(v != pre)
 55         {
 56             dfs1(v,u,d+1);
 57             num[u] += num[v];
 58             if(son[u] == -1 || num[v] > num[son[u]])
 59                 son[u] = v;
 60         }
 61     }
 62 }
 63 void getpos(int u,int sp) //第二遍dfs求出top和p
 64 {
 65     top[u] = sp;
 66     p[u] = pos++;
 67     fp[p[u]] = u;
 68     if(son[u] == -1) return;
 69     getpos(son[u],sp);
 70     for(int i = head[u] ; i != -1; i = edge[i].next)
 71     {
 72         int v = edge[i].to;
 73         if(v != son[u] && v != fa[u])
 74             getpos(v,v);
 75     }
 76 }
 77
 78 //线段树
 79 struct Node
 80 {
 81     int l,r;
 82     int Max;
 83     int Min;
 84     int ne;
 85 }segTree[MAXN*3];
 86 void build(int i,int l,int r)
 87 {
 88     segTree[i].l = l;
 89     segTree[i].r = r;
 90     segTree[i].Max = 0;
 91     segTree[i].Min = 0;
 92     segTree[i].ne = 0;
 93     if(l == r)return;
 94     int mid = (l+r)/2;
 95     build(i<<1,l,mid);
 96     build((i<<1)|1,mid+1,r);
 97 }
 98 void push_up(int i)
 99 {
100     segTree[i].Max = max(segTree[i<<1].Max,segTree[(i<<1)|1].Max);
101     segTree[i].Min = min(segTree[i<<1].Min,segTree[(i<<1)|1].Min);
102 }
103 void push_down(int i)
104 {
105     if(segTree[i].l == segTree[i].r)return;
106     if(segTree[i].ne)
107     {
108         segTree[i<<1].Max = -segTree[i<<1].Max;
109         segTree[i<<1].Min = -segTree[i<<1].Min;
110         swap(segTree[i<<1].Min,segTree[i<<1].Max);
111         segTree[(i<<1)|1].Max = -segTree[(i<<1)|1].Max;
112         segTree[(i<<1)|1].Min = -segTree[(i<<1)|1].Min;
113         swap(segTree[(i<<1)|1].Max,segTree[(i<<1)|1].Min);
114         segTree[i<<1].ne ^= 1;
115         segTree[(i<<1)|1].ne ^= 1;
116         segTree[i].ne = 0;
117     }
118 }
119 void update(int i,int k,int val) // 更新线段树的第k个值为val
120 {
121     if(segTree[i].l == k && segTree[i].r == k)
122     {
123         segTree[i].Max = val;
124         segTree[i].Min = val;
125         segTree[i].ne = 0;
126         return;
127     }
128     push_down(i);
129     int mid = (segTree[i].l + segTree[i].r)/2;
130     if(k <= mid)update(i<<1,k,val);
131     else update((i<<1)|1,k,val);
132     push_up(i);
133 }
134 void ne_update(int i,int l,int r) // 更新线段树的区间[l,r]取反
135 {
136     if(segTree[i].l == l && segTree[i].r == r)
137     {
138         segTree[i].Max = -segTree[i].Max;
139         segTree[i].Min = -segTree[i].Min;
140         swap(segTree[i].Max,segTree[i].Min);
141         segTree[i].ne ^= 1;
142         return;
143     }
144     push_down(i);
145     int mid = (segTree[i].l + segTree[i].r)/2;
146     if(r <= mid)ne_update(i<<1,l,r);
147     else if(l > mid) ne_update((i<<1)|1,l,r);
148     else
149     {
150         ne_update(i<<1,l,mid);
151         ne_update((i<<1)|1,mid+1,r);
152     }
153     push_up(i);
154 }
155 int query(int i,int l,int r)  //查询线段树中[l,r] 的最大值
156 {
157     if(segTree[i].l == l && segTree[i].r == r)
158         return segTree[i].Max;
159     push_down(i);
160     int mid = (segTree[i].l + segTree[i].r)/2;
161     if(r <= mid)return query(i<<1,l,r);
162     else if(l > mid)return query((i<<1)|1,l,r);
163     else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r));
164     push_up(i);
165 }
166 int findmax(int u,int v)//查询u->v边的最大值
167 {
168     int f1 = top[u], f2 = top[v];
169     int tmp = -100000000;
170     while(f1 != f2)
171     {
172         if(deep[f1] < deep[f2])
173         {
174             swap(f1,f2);
175             swap(u,v);
176         }
177         tmp = max(tmp,query(1,p[f1],p[u]));
178         u = fa[f1]; f1 = top[u];
179     }
180     if(u == v)return tmp;
181     if(deep[u] > deep[v]) swap(u,v);
182     return max(tmp,query(1,p[son[u]],p[v]));
183 }
184 void Negate(int u,int v)//把u-v路径上的边的值都设置为val
185 {
186     int f1 = top[u], f2 = top[v];
187     while(f1 != f2)
188     {
189         if(deep[f1] < deep[f2])
190         {
191             swap(f1,f2);
192             swap(u,v);
193         }
194         ne_update(1,p[f1],p[u]);
195         u = fa[f1]; f1 = top[u];
196     }
197     if(u == v)return;
198     if(deep[u] > deep[v]) swap(u,v);
199     return ne_update(1,p[son[u]],p[v]);
200 }
201 int e[MAXN][3];
202 int main()
203 {
204     //freopen("in.txt","r",stdin);
205     //freopen("out.txt","w",stdout);
206     int T;
207     int n;
208     scanf("%d",&T);
209     while(T--)
210     {
211         init();
212         scanf("%d",&n);
213         for(int i = 0;i < n-1;i++)
214         {
215             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
216             addedge(e[i][0],e[i][1]);
217             addedge(e[i][1],e[i][0]);
218         }
219         dfs1(1,0,0);
220         getpos(1,1);
221         build(1,0,pos-1);
222         for(int i = 0;i < n-1; i++)
223         {
224             if(deep[e[i][0]] > deep[e[i][1]])
225                 swap(e[i][0],e[i][1]);
226             update(1,p[e[i][1]],e[i][2]);
227         }
228         char op[10];
229         int u,v;
230         while(scanf("%s",op) == 1)
231         {
232             if(op[0] == 'D')break;
233             scanf("%d%d",&u,&v);
234             if(op[0] == 'Q')
235                 printf("%d\n",findmax(u,v));//查询u->v路径上边权的最大值
236             else if(op[0] == 'C')
237                 update(1,p[e[u-1][1]],v);//改变第u条边的值为v
238             else Negate(u,v);
239         }
240     }
241     return 0;
242 }

POJ 3237 Tree (树链剖分)相关推荐

  1. POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘...

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12247   Accepted: 3151 Descriptio ...

  2. POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

    题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...

  3. CodeForces - 343D Water Tree(树链剖分+线段树)

    题目链接: 题目大意:给出一棵由n个点组成的树,初始时每个点的权值为0,接下来有m个操作,每个操作分为以下三种: 1 x:将包括节点x在内的所有子孙节点的权值都改为1 2 x:将包括节点x在内的所有父 ...

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

    题目链接:点击查看 题目大意:给出一棵由n个点组成的树,再给出数个操作,每次操作分为下列几种类型: QUERY x y:询问点x-点y这条路径上的所有边权的最大值 CHANGE x y:将第x条边的权 ...

  5. 计蒜客 - Distance on the tree(树链剖分+离线处理+线段树)

    题目链接:点击查看 题目大意:给出一颗含有n个节点的树,每条边都有权值,现在给出m个询问,每次询问的格式为u,v,w,我们需要求出在路径u-v上,边权小于等于w的边的个数 题目分析:因为一开始不会主席 ...

  6. HDU - 3804 Query on a tree(树链剖分+线段树+离线处理)

    题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...

  7. HDU 5044 Tree 树链剖分

    树链剖分离线处理所有的增加操作.考虑如果在线性结构上面处理这样的问题,只要把增加区域的起始点+w,结束点的后面一个点-w,最终输出答案的时候只要扫描一遍就好了,现在通过树链剖分把树转化为类似的线性结构 ...

  8. SPOJ 375 query on a tree 树链剖分

    题意: 给一棵树型数据结构 ①支持修改边的权值      ②支持成段边权最值查询 树链剖分入门题. 树链剖分+线段树 用的notonlysuccess的线段树--不开结构体事先预处理的那种 我以前写的 ...

  9. Tree(树链剖分+线段树延迟标记)

    Tree http://poj.org/problem?id=3237 Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12 ...

  10. SPOJ Query on a tree 树链剖分 边修改

    链接 提交链接 题解 对边的修改算到点上 只需要修改下面的地方 代码 #include<bits/stdc++.h> #define N 10010 #define INF 0x3f3f3 ...

最新文章

  1. LeetCode简单题之两个相同字符之间的最长子字符串
  2. Java 25 岁,发展现状大曝光!程序员的机会来了
  3. 只允许指定IP远程桌面连接_使用IP安全策略
  4. 数据可视化的开源方案: Superset vs Redash vs Metabase (一)
  5. oracle exp cluster n,oracle cluster verfication utility failed
  6. wamp无法使用php,使用wamp无法访问www中的php文件
  7. osc mysql_MySQL学习(一) - osc_0sz5p35w的个人空间 - OSCHINA - 中文开源技术交流社区...
  8. python安装matplotlib需要c编译_在Python 3.9上安装matplotlib提示需要FreeType更高版本的解决...
  9. 10 使用ViewPager实现导航
  10. wgan 不理解 损失函数_GAN损失函数||WGAN
  11. 计算机图形学完整笔记(八):曲线曲面 - 2
  12. Android6.0 camera个数探测
  13. STR鉴定原理、流程已经报告数据解读指南
  14. STM32——DAC数模转换实验
  15. 【RDMA】19. RDMA之iWARP Soft-iWARP
  16. Rebuild Project
  17. Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools“(已解决)
  18. Hydration 是什么?
  19. linux mysql 登录报1045_【mysql】linux登录MySQL_报错ERROR_1045_(28000)解决办法
  20. 格鲁伯小升初文学常识必考

热门文章

  1. mysql 升序 字段值为NULL 排在后面
  2. (原)调用jpeglib对图像进行压缩
  3. Unity开发NGUI代码实现ScrollView(放大视图)
  4. Linux -- free 命令 内存适用状态监控
  5. 如何在MFC中调用CUDA
  6. hdu4525 威威猫系列故事——吃鸡腿
  7. Valgrind使用说明
  8. C++基本语法( Visual Studio 2015 )【个人 见解】
  9. js:封装获取当前元素的所有的哥哥元素节点
  10. LeetCode算法题-Minimum Depth of Binary Tree(Java实现)