题目大意:指定一颗树上有3个操作:询问操作,询问a点和b点之间的路径上最长的那条边的长度;取反操作,将a点和b点之间的路径权值都取相反数;变化操作,把某条边的权值变成指定的值。
 #include <cstdio>
#include <iostream>
#include <cstring> using namespace std;
#define N 10010
#define ls o<<1
#define rs o<<1|1
#define define_m int m=(l+r)>>1
const int INF = ;
int first[N] , k;
struct Edge{
int x , y , next , w;
Edge(){}
Edge(int x , int y , int next , int w):x(x),y(y),next(next),w(w){}
}e[N<<]; void add_edge(int x ,int y , int w)
{
e[k] = Edge(x , y , first[x] , w);
first[x] = k++;
} int sz[N] , son[N] , dep[N] , fa[N] , num , id[N] , top[N];
void dfs(int u , int f , int d)
{
sz[u] = , fa[u] = f , son[u] = , dep[u] = d;
int maxn = ;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f) continue;
dfs(v , u , d+);
sz[u] += sz[v];
if(maxn<sz[v]) maxn = sz[v] , son[u] = v;
}
} void dfs1(int u , int f , int head)
{
id[u] = ++num , top[u] = head;
if(son[u]) dfs1(son[u] , u , head);
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f || v==son[u]) continue;
dfs1(v , u , v);
}
} int mx[N<<] , mn[N<<] , neg[N<<] , val[N]; void push_down(int o)
{
if(neg[o]<){
neg[ls]*=neg[o] , neg[rs]*=neg[o];
int tmp;
tmp = mx[ls] , mx[ls] = -mn[ls] , mn[ls] = -tmp;
tmp = mx[rs] , mx[rs] = -mn[rs] , mn[rs] = -tmp;
neg[o] = ;
}
} void push_up(int o)
{
mx[o] = max(mx[ls] , mx[rs]);
mn[o] = min(mn[ls] , mn[rs]);
} void build(int o , int l , int r)
{
neg[o] = ;
if(l==r){
mx[o] = mn[o] = val[l];
return ;
}
define_m;
build(ls , l , m);
build(rs , m+ , r);
push_up(o);
} void change(int o , int l , int r , int p , int v)
{
if(l==r){
mx[o] = mn[o] = v;
return;
}
push_down(o);
define_m;
if(m>=p) change(ls , l , m , p , v);
else change(rs , m+ , r , p , v);
push_up(o);
} void update(int o , int l , int r , int s , int t)
{
if(l>=s && r<=t){
int tmp;
tmp = mx[o] , mx[o] = -mn[o] , mn[o] = -tmp;
neg[o] *= -;
return ;
}
push_down(o);
define_m;
if(m>=s) update(ls , l , m , s , t);
if(m<t) update(rs , m+ , r , s , t);
push_up(o);
} int query(int o , int l , int r , int s , int t)
{
if(l>=s && r<=t) return mx[o];
push_down(o);
define_m;
int ans = -INF;
if(m>=s) ans=max(ans , query(ls , l , m , s , t));
if(m<t) ans=max(ans , query(rs , m+ , r , s , t));
return ans;
}
int n , u , v , w;
char str[]; void negatePath(int u , int v)
{
int top1 = top[u] , top2 = top[v];
while(top1!=top2)
{
if(dep[top1]<dep[top2]){
swap(top1 , top2);
swap(u , v);
}
update( , , num , id[top1] , id[u]);
u = fa[top1];
top1 = top[u];
}
if(u!=v){
if(dep[u]<dep[v]) swap(u , v);
update( , , num , id[son[v]] , id[u]);
}
} int calPath(int u , int v)
{
int top1 = top[u] , top2 = top[v];
int ret = -INF;
while(top1!=top2){
if(dep[top1]<dep[top2]){
swap(top1 , top2);
swap(u , v);
}
ret = max(ret , query( , , num , id[top1] , id[u]));
u = fa[top1];
top1 = top[u];
}
if(u!=v){
if(dep[u]<dep[v]) swap(u , v);
ret = max(ret , query( , , num , id[son[v]] , id[u]));
}
return ret;
} int main()
{
// freopen("in.txt" , "r" , stdin);
int T;
scanf("%d" , &T);
while(T--)
{
scanf("%d" , &n);
memset(first , - , sizeof(first));
k=;
for(int i= ; i<n- ; i++){
scanf("%d%d%d" , &u ,&v , &w);
add_edge(u , v , w);
add_edge(v , u , w);
}
num = ;
dfs( , , );
dfs1( , , );
for(int i= ; i<n ; i++){
int j=i<< , x=e[j].x , y=e[j].y;
if(fa[x]!=y) val[id[y]] = e[j].w;
else val[id[x]] = e[j].w;
}
build( , , num);
while(scanf("%s" , str)){
if(str[] == 'D') break;
if(str[] == 'C'){
scanf("%d%d" , &u , &v);
u--;
int x = e[u*].x , y = e[u*].y , pos;
if(fa[x]!=y) pos = id[y];
else pos = id[x];
change( , , num , pos , v);
}
else if(str[] == 'N'){
scanf("%d%d" , &u , &v);
negatePath(u , v);
}
else{
scanf("%d%d" , &u , &v);
int ret = calPath(u , v);
printf("%d\n" , ret);
}
}
}
return ;
}

POJ 3237的更多相关文章

  1. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  2. poj 3237 Tree [LCA] (树链剖分)

    poj 3237 tree inline : 1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高. 2. 很明显,类 ...

  3. poj 3237 Tree(树链拆分)

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

  4. HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  5. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  6. POJ 3237:Tree(树链剖分)

    http://poj.org/problem?id=3237 题意:树链剖分.操作有三种:改变一条边的边权,将 a 到 b 的每条边的边权都翻转(即 w[i] = -w[i]),询问 a 到 b 的最 ...

  7. poj 3237 Tree 树链剖分

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

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

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

  9. ●POJ 3237 Tree

    题链: http://poj.org/problem?id=3237 题解: LCT 说一说如何完成询问操作就好了(把一条链的边权变成相反数的操作可以类比着来): 首先明确一下,我们把边权下放到点上. ...

  10. POJ 3237 树链剖分

    题目链接:http://poj.org/problem?id=3237 题意:给定一棵n个结点n-1条边的树. 每条边都是一个边权. 现在有4种操作 1:CHANGE I V:把(输入的)第i条边的边 ...

随机推荐

  1. android模拟器中文乱码

    问题:在xml文件中设置的中文能正确输出,但是在java文件中设置的中文会在模拟器上呈现乱码 解决方案:在build.gradle文件中添加一行代码 android {compileOptions.e ...

  2. 加速Eclipse使其成为超快的IDE

    按照下述步骤来加速Eclipse为超快的IDE,它适用于32和64位版本的Eclipse /JDK(OS为64位Windows 7). 1.禁用防病毒软件,或将JDK.Eclipse.workspac ...

  3. SenchaTouch介绍和Sencha Architect介绍以及安装

    一.SenchaTouch介绍 Sencha Touch框架是世界上第一个基于HTML 5的Mobile App框架. 在Sencha Touch这个名词中,包括了两个组成部分,其中Sencha的前身 ...

  4. 转!JNDI 是什么?

    JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有 ...

  5. python语法笔记(三)

    1. 动态类型 python的变量不需要声明,在赋值时,变量可以赋值为任意的值.这和Python的动态类型语言相关. python对象是存在于内存中的实体,代码中写对象名,只是指向该对象的引用.引用和 ...

  6. js生成验证码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. tcp服务的测试程序开源

    开源的是一个测试客户端,可以用来检验服务器端程序的并发处理能力. 使用方法为: python epolltest.py --host=192.168.15.128 --port=8809 --degr ...

  8. [你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理

    原文地址:http://kb.cnblogs.com/page/42318/ 系列文章导航: [你必须知道的.NET] 开篇有益 [你必须知道的.NET] 第一回:恩怨情仇:is和as [你必须知道的 ...

  9. 获取本机 Android 默认sha1 秘钥

    获取本机 Android 默认sha1 秘钥: 以Windows操作系统为例,打开CMD,运行以下指令将得到所有默认秘钥. keytool -list -v -keystore C:\Users\pa ...

  10. GIT命令(急速学习)

    用过sourceTree,egit(eclipse中的git插件),最后还是感觉git bash顺手:svn早已经不用:   先上几个原来看过的git 教程--书读百遍,其义自见.多看几篇文章才能总结 ...