Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 7384   Accepted: 2001

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
/*
poj3237 树链部分
感觉是比较不错的题目,主要是线段树掌握不怎么好导致一直有问题。
查询最大值 + 修改边 + 区间置反
先处理出树链,然后再上值
push_up 和 push_down函数
hhh-2016-2-2 3:46:58
*/ #include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <Map>
using namespace std;
typedef long long ll;
typedef long double ld; using namespace std; const int maxn = 100010; struct node
{
int to,next;
} edge[maxn*2]; int head[maxn];
int top[maxn]; //链的顶端节点
int far[maxn]; //父亲
int dep[maxn]; //深度
int num[maxn]; //表示以x为根的子树的节点数
int p[maxn]; //p[u]表示边u所在的位置
int fp[maxn]; //与p相对应
int son[maxn]; //重儿子
int tot,pos;
void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot ++;
} void dfs(int u,int fa,int d) //先处理出重儿子、dep、far、num
{
dep[u] = d;
far[u] = fa;
num[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != fa)
{
dfs(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
} void getpos(int u,int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1) return ;
getpos(son[u],sp);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != far[u] && v != son[u])
getpos(v,v);
}
} struct Node
{
int l,r;
int flag;
int Max,Min;
} segtree[maxn*3]; void build(int i,int l,int r)
{
segtree[i].l = l;
segtree[i].r = r;
segtree[i].Max = 0;
segtree[i].Min = 0;
segtree[i].flag = 0;
if(l == r)
return ;
int mid = (l+r)/2;
build(i<<1,l,mid);
build((i<<1)|1,mid+1,r);
} void push_up(int i)
{
segtree[i].Max = max(segtree[i<<1].Max,segtree[(i<<1)|1].Max);
segtree[i].Min = min(segtree[i<<1].Min,segtree[(i<<1)|1].Min);
} void push_down(int i)
{
if(segtree[i].l == segtree[i].r)
return ;
if(segtree[i].flag)
{
segtree[i<<1].Max = -segtree[i<<1].Max;
segtree[i<<1].Min = -segtree[i<<1].Min;
swap(segtree[i<<1].Max,segtree[i<<1].Min);
segtree[i<<1].flag ^= 1; segtree[(i<<1)|1].Max = -segtree[(i<<1)|1].Max;
segtree[(i<<1)|1].Min = -segtree[(i<<1)|1].Min;
segtree[(i<<1)|1].flag ^= 1;
swap(segtree[(i<<1)|1].Max,segtree[(i<<1)|1].Min); segtree[i].flag = 0;
}
} void update(int i,int k,int val)
{
if(segtree[i].l == k && segtree[i].r == k)
{
segtree[i].Max = val;
segtree[i].Min = val;
segtree[i].flag = 0;
return ;
}
push_down(i);
int mid = (segtree[i].l+segtree[i].r)>>1;
if(k <= mid) update(i<<1,k,val);
else update((i<<1)|1,k,val);
push_up(i);
} void negat(int i,int l,int 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].flag ^= 1;
return;
}
push_down(i);
int mid = (segtree[i].l+segtree[i].r)>>1;
if(r <= mid) negat(i<<1,l,r);
else if(l > mid) negat((i<<1)|1,l,r);
else
{
negat(i<<1,l,mid);
negat((i<<1)|1,mid+1,r);
}
push_up(i);
} int query(int i,int l,int 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)>>1;
if(r <= mid) return query(i<<1,l,r);
else if(l > mid) return query((i<<1)|1,l,r);
else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r));
push_up(i);
} int fin(int l,int r)
{
int f1 = top[l];
int f2 = top[r];
int tt = -100000000;
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(l,r);
}
tt = max(query(1,p[f1],p[l]),tt);
l = far[f1];
f1 = top[l];
}
if(l == r)
return tt;
if(dep[l] > dep[r]) swap(l,r);
return max(tt,query(1,p[son[l]],p[r]));
} void change(int l,int r)
{
int f1 = top[l];
int f2 = top[r];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2);
swap(l,r);
}
negat(1,p[f1],p[l]);
l = far[f1];
f1 = top[l];
}
if(l == r) return ;
if(dep[l] > dep[r]) swap(l,r);
negat(1,p[son[l]],p[r]);
} void ini()
{
tot = 0;
pos = 1;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
} int me[maxn][2];
int va[maxn]; int main()
{
int T;
int n;
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ini();
for(int i = 1; i < n; i++)
{
scanf("%d%d%d",&me[i][0],&me[i][1],&va[i]);
addedge(me[i][0],me[i][1]);
addedge(me[i][1],me[i][0]);
} dfs(1,0,0);
getpos(1,1);
build(1,1,n);
for(int i = 1; i < n; i++)
{
if(dep[me[i][0]] > dep[me[i][1]])
swap(me[i][0],me[i][1]);
update(1,p[me[i][1]],va[i]);
}
char ch[10];
while(scanf("%s",ch) == 1)
{
;
if(ch[0] == 'D') break;
int u,v;
scanf("%d%d",&u,&v);
if(ch[0] == 'Q')
printf("%d\n",fin(u,v));
else if(ch[0] == 'N')
change(u,v);
else
update(1,p[me[u][1]],v);
}
}
return 0;
}

  

poj3237 树链部分 边权模板的更多相关文章

  1. 树链剖分边权模板spoj375

    树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...

  2. poj3237树链剖分边权+区间取负

    树链剖分+线段树lazy-tag在树链上操作时千万不要写错.. /* 树链剖分+线段树区间变负 */ #include<iostream> #include<cstring> ...

  3. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  4. POJ3237 Tree 树链剖分 边权

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

  5. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  6. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  7. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  8. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

  9. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

随机推荐

  1. Hibernate之深入Hibernate的映射文件

    这周周末 要把hibernate的映射文件搞定 .. 1.映射文件的主结构 主要结构  :根元素为<hibernate-mapping ></hibernate-mapping> ...

  2. 《javascript设计模式与开发实践》阅读笔记(12)—— 享元模式

    享元模式 享元(flyweight)模式是一种用于性能优化的模式,"fly"在这里是苍蝇的意思,意为蝇量级.享元模式的核心是运用共享技术来有效支持大量细粒度的对象. 享元模式的核心 ...

  3. php的控制器链

    控制器之间协同工作就形成了控制器链· 比如在一个控制器的方法中,创建另外一个·控制器,创建对象,然后调用第二个控制器方法,那么在第一个控制器分配给视图的变量,在 第二个控制器的方法中对应的视图也是可以 ...

  4. 谈谈ASP.NET Core中的ResponseCaching

    前言 前面的博客谈的大多数都是针对数据的缓存,今天我们来换换口味.来谈谈在ASP.NET Core中的ResponseCaching,与ResponseCaching关联密切的也就是常说的HTTP缓存 ...

  5. ( 转 ) CORS 有一次 OPTIONS 请求的原理

    刚接触前端的时候,以为HTTP的Request Method只有GET与POST两种,后来才了解到,原来还有HEAD.PUT.DELETE.OPTIONS-- 目前的工作中,HEAD.PUT.DELE ...

  6. Linux之Shell命令

    开始接触Linux命令行,学习Linux文件系统导航以及创建.删除.处理文件所需的命令.  注:文末有福利! 几个快捷键: Linux发行版通常使用Ctrl+Alt组合键配合F1~F7进入要使用的控制 ...

  7. mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦

    以前学习这一块的时候,是说:假设建立了联合索引a+b,那么查询语句也一定要是这个顺序才能应用该索引. 那么实际是怎样呢,经过mysql这么多次版本升级,相信mysql已经给我们做了某些优化. 下面是我 ...

  8. Python系列之 - 装饰器

    装饰器主要是用来对函数的操作,我们把定义的函数比作一个蛋糕的话,那么装饰器就是盒子,如果要吃蛋糕就先打开盒子.具体到程序中就是在函数外层又套了一层,套的那一层就是一个装饰器.这么说可能有点抽象,那么我 ...

  9. beautiful soup

    beautiful soup是一个可以从html或者xml文件中提取数据的python库,它能够通过你喜欢的转换器实现惯用的文档导航.查找.修改文档的方式. beautiful soup 会帮你节省数 ...

  10. 遗传算法详解(LINGO及MatlabGA工具箱求解实现)

    遗传算法 1.前言 遗传算法是一种基于生物界自然群体遗传进化机制的自适应全局优化概率搜索算法.它与传统算法不同,不依赖梯度信息,而是通过模拟自然进化过程来搜索最优解. 例子:兔子的遗传进化 有人说,现 ...