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

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

1

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

Sample Output

1
3

Source

 
 
 

题意就是: 有T组数据 ,给你n个点的树,有三种操作:

1.CHANGE i v :将第i条边的值改为v

2.NEGATE a b :将a点到b点路径上的边权取反

3.QUERY a b :查询a点到b点路径上最大的边权值,

由于有取反操作,记录最大和最小值 然后取反并交换就可以,用线段树来维护,真香警告。。。

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e4+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 int head[maxn],cnt,num,n; struct Edge{
int to,next;
}edge[maxn<<]; void add(int u,int v)//存图(树)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
} int val[maxn],siz[maxn],dep[maxn],son[maxn];
int top[maxn],tid[maxn],pos[maxn],fa[maxn]; void init()//初始化
{
memset(head,-,sizeof(head));
memset(son,-,sizeof(son));
cnt=num=;
} ///树链剖分部分
void dfs1(int u,int father)//第一遍dfs,可以得到当前节点的父亲节点,当前节点的深度,当前节点的重儿子
{
//更新dep,fa,siz数组
siz[u]=;//保存以u为根的子树节点个数
fa[u]=father;//保存爸爸
dep[u]=dep[father]+;//记录深度
for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点
int v=edge[i].to;
if(v!=father){//如果连接的是当前节点的父亲节点,则不处理
dfs1(v,u);
siz[u]+=siz[v];//直接子树节点相加,当前节点的size加上子节点的size
if(son[u]==-||siz[v]>siz[son[u]])//如果没有设置过重节点son或者子节点v的size大于之前记录的重节点son,进行更新
son[u]=v;//保存重儿子
}
}
} void dfs2(int u,int tp)//将各个重节点连接成重链,轻节点连接成轻链,并且将重链(区间)用数据结构(一般是树状数组或者线段树)来维护,并且为每个节点进行编号,其实就是dfs在执行时的顺序(tid数组),以及当前节点所在链的起点(top数组)还有当前节点在树中的位置(pos) )
{
top[u]=tp;//保存当前节点所在的链的顶端节点,当前节点的起点
tid[u]=++num;//保存树中每个节点剖分以后的新编号(dfs的执行顺序)
pos[tid[u]]=u;//保存当前节点在树中的位置,设置dfs序号对应成当前节点
if(son[u]==-) return ;//如果当前节点没有处在重链上,则不处理
dfs2(son[u],tp);//将这条重链上的所有节点都设置成起始的重节点
for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点
int v=edge[i].to;//如果连接节点不是当前节点的重节点并且也不是u的父节点,则将其的top设置成自己,进一步递归
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
} int lazy[maxn<<],Max[maxn<<],Min[maxn<<]; //线段树部分
void Swap(int &x,int &y){int t=x;x=-y;y=-t;} void pushup(int rt)
{
Max[rt]=max(Max[rt<<],Max[rt<<|]);
Min[rt]=min(Min[rt<<],Min[rt<<|]);
} void pushdown(int rt)
{
if(lazy[rt]){
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
if(lazy[rt]&){ //两个子区间是否取反依靠当前区间的懒惰标记判断,判断奇偶
Swap(Max[rt<<],Min[rt<<]);
Swap(Max[rt<<|],Min[rt<<|]);
}
lazy[rt]=;
}
} void build(int l,int r,int rt)
{
lazy[rt]=;
if(l==r){
Max[rt]=Min[rt]=;
return ;
} int m=(l+r)>>;
build(lson);
build(rson);
pushup(rt);
} void update(int pos,int val,int l,int r,int rt)
{
if(l==r&&l==pos){
Max[rt]=val;Min[rt]=val;lazy[rt]=;
return ;
} pushdown(rt);
int m=(l+r)>>;
if(pos<=m) update(pos,val,lson);
else update(pos,val,rson);
pushup(rt);
} void Negate(int L,int R,int l,int r,int rt)//Negate是int tmp=Max,Max=-Min,Min=-tmp
{
if(L<=l&&r<=R){
lazy[rt]++;
Swap(Max[rt],Min[rt]);//这里要马上取反
return ;
} pushdown(rt);
int m=(l+r)>>;
if(L<=m) Negate(L,R,lson);
if(R> m) Negate(L,R,rson);
pushup(rt);
} int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){
return Max[rt];
} pushdown(rt);
int ret=-inf;
int m=(l+r)>>;
if(L<=m) ret=max(ret,query(L,R,lson));
if(R> m) ret=max(ret,query(L,R,rson));
pushup(rt);
return ret;
} int get_max(int u,int v)
{
int ans=-<<;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans=max(ans,query(tid[top[u]],tid[u],,n,));
u=fa[top[u]];
} if(dep[v]<dep[u]) swap(u,v);
ans=max(ans,query(tid[son[u]],tid[v],,n,));//这里写捞了,tid[son[u]],写成tid[u],wa了好几天。。。
printf("%d\n",ans);
} void change(int u,int v)
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
Negate(tid[top[u]],tid[u],,n,);
u=fa[top[u]];
} if(u==v) return ;
if(dep[v]<dep[u]) swap(u,v);
Negate(tid[son[u]],tid[v],,n,);
} struct eg{
int u,v,val;
}eg[maxn]; int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(int i=;i<n;i++){
scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].val);
add(eg[i].u,eg[i].v);//加边
add(eg[i].v,eg[i].u);//加边
}
dfs1(,);//第一遍dfs
dfs2(,);//第二遍dfs
build(,n,);
for(int i=;i<n;i++){
if(dep[eg[i].u]<dep[eg[i].v]) swap(eg[i].u,eg[i].v);
update(tid[eg[i].u],eg[i].val,,n,);
}
int a,b;
char op[];
while(scanf("%s",op)&&op[]!='D'){
scanf("%d%d",&a,&b);
if(op[]=='Q'){
get_max(a,b);
}
if(op[]=='C'){
update(tid[eg[a].u],b,,n,);
}
if(op[]=='N'){
change(a,b);
}
}
}
}

哈哈哈哈,加油加油。

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

  1. poj 3237 Tree 树链剖分

    题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...

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

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

  3. poj 3237 Tree 树链剖分+线段树

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

  4. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  5. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  6. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  7. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  8. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

  9. SPOJ Query on a tree 树链剖分 水题

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

随机推荐

  1. HihoCoder 1480:矩阵填数 (杨氏矩阵 || 钩子公式 + 筛逆元)

    描述 小Hi在玩一个游戏,他需要把1, 2, 3, ... NM填入一个N行M列的矩阵中,使得矩阵每一行从左到右.每一列从上到下都是递增的. 例如如下是3x3的一种填法: 136 247 589 给定 ...

  2. 工具——SVN常用命令

    SVN一般都是团队合作做一个项目所需用到的,为了是版本的统一 ;1. Check out——从服务器端取得代码    把服务器资料库里存放的某个项目代码取出来,放到本地主机中,这个动作叫做“check ...

  3. CodeForces743E. Vladik and cards 二分+状压dp

    这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有 ...

  4. git使用笔记(一)入门

    By francis_hao    Nov 17,2016 本来是想把git的使用笔记写在一个文件里,但是越写越长,最后也不得不分开了.这样也好,每一篇一个侧重,可以写的详细一点.   初学乍练 在l ...

  5. JavaScript学习笔记——浅拷贝、深拷贝

    参考自:http://www.cnblogs.com/yichengbo/archive/2014/07/10/3835882.html 一.数组的深浅拷贝 在使用JavaScript对数组进行操作的 ...

  6. 代码管理工具 (含git、npm、gulp)

    1 Git 分布式代码管理工具(基于Linux,可在本地进行提交)代码同时储存在本地和服务器中 ① Git基本操作命令 (1)初始化,创建初始化仓库 git init ------- 文件初始化,初始 ...

  7. iBatis之Iterator的使用

    一:前言 现在这个项目使用的是iBatis,我刚刚开始的时候说是用MyBatis,因为我以前用过,觉得还是比较好用的啊,而且不像iBatis样,查什么一个字段不能多也不能少,觉得好无语啊. 二:内容 ...

  8. SQL优化之一

    使用union代替or,可以提升查询效率. 使用or时,会自动放弃已有的索引

  9. Nodejs写的搬家工具知识分享

    这篇文章 主要学习这两个模块的使用: request-promise-native : https://github.com/request/request-promise-native cheeri ...

  10. keras_实现cnn_手写数字识别

    # conding:utf-8 import os os.environ[' import numpy as np from keras.models import Sequential from k ...