POJ 3237 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 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
树链剖分+线段树实现
/* ***********************************************
Author :kuangbin
Created Time :2013/8/17 4:04:42
File Name :F:\2013ACM练习\专题学习\数链剖分\POJ3237Tree.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std; const int MAXN = ;
struct Edge
{
int to,next;
}edge[MAXN*];
int head[MAXN],tot;
int top[MAXN];//top[v]表示v所在的重链的顶端节点
int fa[MAXN]; //父亲节点
int deep[MAXN];//深度
int num[MAXN];//num[v]表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[MAXN];//和p数组相反
int son[MAXN];//重儿子
int pos;
void init()
{
tot = ;
memset(head,-,sizeof(head));
pos = ;
memset(son,-,sizeof(son));
}
void addedge(int u,int v)
{
edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;
}
void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son
{
deep[u] = d;
fa[u] = pre;
num[u] = ;
for(int i = head[u];i != -; i = edge[i].next)
{
int v = edge[i].to;
if(v != pre)
{
dfs1(v,u,d+);
num[u] += num[v];
if(son[u] == - || num[v] > num[son[u]])
son[u] = v;
}
}
}
void getpos(int u,int sp) //第二遍dfs求出top和p
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -) return;
getpos(son[u],sp);
for(int i = head[u] ; i != -; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
} //线段树
struct Node
{
int l,r;
int Max;
int Min;
int ne;
}segTree[MAXN*];
void build(int i,int l,int r)
{
segTree[i].l = l;
segTree[i].r = r;
segTree[i].Max = ;
segTree[i].Min = ;
segTree[i].ne = ;
if(l == r)return;
int mid = (l+r)/;
build(i<<,l,mid);
build((i<<)|,mid+,r);
}
void push_up(int i)
{
segTree[i].Max = max(segTree[i<<].Max,segTree[(i<<)|].Max);
segTree[i].Min = min(segTree[i<<].Min,segTree[(i<<)|].Min);
}
void push_down(int i)
{
if(segTree[i].l == segTree[i].r)return;
if(segTree[i].ne)
{
segTree[i<<].Max = -segTree[i<<].Max;
segTree[i<<].Min = -segTree[i<<].Min;
swap(segTree[i<<].Min,segTree[i<<].Max);
segTree[(i<<)|].Max = -segTree[(i<<)|].Max;
segTree[(i<<)|].Min = -segTree[(i<<)|].Min;
swap(segTree[(i<<)|].Max,segTree[(i<<)|].Min);
segTree[i<<].ne ^= ;
segTree[(i<<)|].ne ^= ;
segTree[i].ne = ;
}
}
void update(int i,int k,int val) // 更新线段树的第k个值为val
{
if(segTree[i].l == k && segTree[i].r == k)
{
segTree[i].Max = val;
segTree[i].Min = val;
segTree[i].ne = ;
return;
}
push_down(i);
int mid = (segTree[i].l + segTree[i].r)/;
if(k <= mid)update(i<<,k,val);
else update((i<<)|,k,val);
push_up(i);
}
void ne_update(int i,int l,int r) // 更新线段树的区间[l,r]取反
{
if(segTree[i].l == l && segTree[i].r == r)
{
segTree[i].Max = -segTree[i].Max;
segTree[i].Min = -segTree[i].Min;
swap(segTree[i].Max,segTree[i].Min);
segTree[i].ne ^= ;
return;
}
push_down(i);
int mid = (segTree[i].l + segTree[i].r)/;
if(r <= mid)ne_update(i<<,l,r);
else if(l > mid) ne_update((i<<)|,l,r);
else
{
ne_update(i<<,l,mid);
ne_update((i<<)|,mid+,r);
}
push_up(i);
}
int query(int i,int l,int r) //查询线段树中[l,r] 的最大值
{
if(segTree[i].l == l && segTree[i].r == r)
return segTree[i].Max;
push_down(i);
int mid = (segTree[i].l + segTree[i].r)/;
if(r <= mid)return query(i<<,l,r);
else if(l > mid)return query((i<<)|,l,r);
else return max(query(i<<,l,mid),query((i<<)|,mid+,r));
push_up(i);
}
int findmax(int u,int v)//查询u->v边的最大值
{
int f1 = top[u], f2 = top[v];
int tmp = -;
while(f1 != f2)
{
if(deep[f1] < deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp = max(tmp,query(,p[f1],p[u]));
u = fa[f1]; f1 = top[u];
}
if(u == v)return tmp;
if(deep[u] > deep[v]) swap(u,v);
return max(tmp,query(,p[son[u]],p[v]));
}
void Negate(int u,int v)//把u-v路径上的边的值都设置为val
{
int f1 = top[u], f2 = top[v];
while(f1 != f2)
{
if(deep[f1] < deep[f2])
{
swap(f1,f2);
swap(u,v);
}
ne_update(,p[f1],p[u]);
u = fa[f1]; f1 = top[u];
}
if(u == v)return;
if(deep[u] > deep[v]) swap(u,v);
return ne_update(,p[son[u]],p[v]);
}
int e[MAXN][];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int n;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i = ;i < n-;i++)
{
scanf("%d%d%d",&e[i][],&e[i][],&e[i][]);
addedge(e[i][],e[i][]);
addedge(e[i][],e[i][]);
}
dfs1(,,);
getpos(,);
build(,,pos-);
for(int i = ;i < n-; i++)
{
if(deep[e[i][]] > deep[e[i][]])
swap(e[i][],e[i][]);
update(,p[e[i][]],e[i][]);
}
char op[];
int u,v;
while(scanf("%s",op) == )
{
if(op[] == 'D')break;
scanf("%d%d",&u,&v);
if(op[] == 'Q')
printf("%d\n",findmax(u,v));//查询u->v路径上边权的最大值
else if(op[] == 'C')
update(,p[e[u-][]],v);//改变第u条边的值为v
else Negate(u,v);
}
}
return ;
}
POJ 3237 Tree (树链剖分)的更多相关文章
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- poj 3237 Tree(树链拆分)
题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
随机推荐
- SPOJ JZPLIT
Problem SPOJ Solution 考虑任意一个作为矩阵四个角的位置 \(r_i \oplus c_j\oplus a_{i,j}\oplus x_{i,j}=0\) \(r_i \oplus ...
- openjudge-NOI 2.6-1768 最大子矩阵
题目链接:http://noi.openjudge.cn/ch0206/1768/ 题解: 如果用O(n4)的算法肯定会炸,需要压缩掉一维的空间,只需要简单加和就好啦 例如,我们要对样例中第2-4行D ...
- java基础11 继承(super、extends关键字和重写,这三个要素出现的前提:必须存在继承关系)
面向对象的三大特征: 1.封装 (将一类属性封装起来,并提供set()和get()方法给其他对象设置和获取值.或者是将一个运算方法封装起来,其他对象需要此种做运算时,给此对象调用) 2.继承 ...
- Effective C++笔记(六):继承与面向对象设计
参考:http://www.cnblogs.com/ronny/p/3756494.html 条款32:确定你的public继承塑模出is-a关系 “public继承”意味着is-a.适用于base ...
- Codeforces 822D My pretty girl Noora(最小素因子的性质)
题目大意:一场选美比赛有N个人,可以分成N/x,每组x人.每组的比较次数为x(x-1)/2,f[N]为最后决出冠军所需的比较次数,可以通过改变x的值使f[N]改变.题目给出t,l,r(1 ≤ t &l ...
- golang基础之三-字符串,时间,流程控制,函数
strings和strconv的使用 strings strings.HasPrefix(s string,preffix string) bool:判断字符串s是否以prefix开头 stirngs ...
- linux 命令route add default dev eth0和route add default gw eth0的区别?
https://blog.csdn.net/zhaogezhuoyuezhao/article/details/7339220
- jquery validate表单验证插件的基本使用方法及功能拓展
1 表单验证的准备工作 在开启长篇大论之前,首先将表单验证的效果展示给大家. 1.点击表单项,显示帮助提示 2.鼠标离开表单项时,开始校验元素 3.鼠标离开后的正确.错误提示及鼠标移入时的帮助提 ...
- poj1606 Jugs(BFS)
题目链接 http://poj.org/problem?id=1606 题意 有两个容量分别为ca,cb的杯子,可以向杯子里倒水,将杯子里的水倒空,将一个杯子里的水倒到另一个杯子里,求怎样倒才能使其中 ...
- centos6.5 下安装mysql5.7
http://blog.csdn.net/cryhelyxx/article/details/49757217 按步骤一路执行下去. 以下是补充: linux下,在mysql正常运行的情况下,输入my ...