题目链接:http://poj.org/problem?id=3237

题目大意:指定一颗树上有3个操作:

1)询问操作,询问a点和b点之间的路径上最长的那条边的长度(即最大值);

2)取反操作,将a点和b点之间的路径权值都取相反数;

3)变化操作,把某条边的权值变成指定的值。

分析:树链剖分,线段树维护好区间的最大最小值,方便取反操作更新。。。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct edge
{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}e[N<<];
int head[N<<],tot;
int top[N];//top[v]表示v所在的重链的顶端节点
int fa[N];//父亲节点
int dep[N];//深度
int sz[N];//si[v]表示以v为根节点的子树的节点数
int son[N];//重儿子
int p[N];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[N];//与p数组相反
int pos;//所有链构成的线段树总长度
int mx[N<<],mn[N<<],col[N<<],E[N][];
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void init()
{
tot=;FILL(head,-);
pos=;FILL(son,-);
}
void dfs(int u,int f,int d)
{
dep[u]=d;sz[u]=;fa[u]=f;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v==f)continue;
dfs(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[son[u]]<sz[v])son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=++pos;
fp[pos]=u;
if(son[u]==-)return;
getpos(son[u],sp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
{
getpos(v,v);
}
}
}
void Pushup(int rt)
{
int ls=rt<<,rs=ls|;
mx[rt]=max(mx[ls],mx[rs]);
mn[rt]=min(mn[ls],mn[rs]);
}
void Pushdown(int rt)
{
int ls=rt<<,rs=ls|;
if(col[rt])
{
mx[ls]=-mx[ls];
mn[ls]=-mn[ls];
swap(mx[ls],mn[ls]);
mx[rs]=-mx[rs];
mn[rs]=-mn[rs];
swap(mx[rs],mn[rs]);
col[ls]^=;col[rs]^=;
col[rt]=;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(c!=inf)
{
mx[rt]=mn[rt]=c;
col[rt]=;
}
else
{
col[rt]^=;
mx[rt]=-mx[rt];
mn[rt]=-mn[rt];
swap(mn[rt],mx[rt]);
}
return;
}
Pushdown(rt);
int m=(l+r)>>;
if(L<=m)update(L,R,c,lson);
if(m<R)update(L,R,c,rson);
Pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return mx[rt];
Pushdown(rt);
int m=(l+r)>>;
int res=-inf;
if(L<=m)res=max(res,query(L,R,lson));
if(m<R)res=max(res,query(L,R,rson));
return res;
}
int lca(int u,int v,int flag)
{
int fu=top[u],fv=top[v];
int res=-inf;
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
if(flag)res=max(res,query(p[fu],p[u],,pos,));
else update(p[fu],p[u],inf,,pos,);
u=fa[fu];fu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
if(u!=v)
{
if(flag)res=max(res,query(p[son[u]],p[v],,pos,));
else update(p[son[u]],p[v],inf,,pos,);
}
return res;
}
int main()
{
int T,n,u,v;
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][]);
}
dfs(,,);
getpos(,);
for(int i=;i<n;i++)
{
if(dep[E[i][]]>dep[E[i][]])
swap(E[i][],E[i][]);
update(p[E[i][]],p[E[i][]],E[i][],,pos,);
}
char op[];
while()
{
scanf("%s",op);
if(op[]=='D')break;
scanf("%d%d",&u,&v);
if(op[]=='Q')
printf("%d\n",lca(u,v,));
else if(op[]=='N')lca(u,v,);
else update(p[E[u][]],p[E[u][]],v,,pos,);
}
}
}

poj3237(树链剖分)的更多相关文章

  1. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

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

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

  3. poj3237 树链剖分 暴力

    NEGATE a,b 将a b间的线段取反,这题应该用线段树+成段更新.我成段更新写的挫了,试了暴力修改过了(数据水). 也是简单的题目.不过要注意点和边的区别. #include<queue& ...

  4. 【POJ3237】Tree(树链剖分)

    题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n& ...

  5. 【POJ3237】Tree(树链剖分+线段树)

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

  6. Cogs 1583. [POJ3237]树的维护 LCT,树链剖分

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆   输入文件:maintaintree.in  ...

  7. POJ3237 Tree 树链剖分 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...

  8. [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...

  9. POJ3237 Tree 树链剖分 边权

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

  10. 【POJ3237】【树链剖分】Tree

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

随机推荐

  1. 怎样使用 App Studio 高速定制你自己的 Universal Windows App

    今天之所以在写一篇关于 App Studio 的文章是由于,App Studio 经过了几次升级功能得到了明显提升还能够调用系统功能了.而且能够更方便的和应用商店关联公布 Universal Wind ...

  2. The Dole Queue

    The Dole Queue Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit cid ...

  3. 译文:前端性能的重要性 The Importance of Frontend Performance

    欢迎訪问我的主页.最新的文章我会首先公布在个人主页上: http://blog.guaidm.com/shocky/ 原书下载地址:http://pan.baidu.com/s/1pJocRwB 在我 ...

  4. Mac 安装工具包brew

    linux有命令行工具 apt-get ,Mac 下也有类似的brew 也就是HomeBrew 网址:http://brew.sh/index_zh-cn.html 可以看到mac安装的时候只需要执行 ...

  5. StackOverFlow的2016统计

    http://stackoverflow.com/research/developer-survey-2016

  6. 查看内存数据的函数(ByteToHex和ByteToBin,最终都变成String)

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. javascript事件委托,事件代理,元素绑定多个事件之练习篇

    <ul id="parent-list"> <li id="post-1">item1</li> <li id=&qu ...

  8. android Activity切换动画效果

    为Activity设置左右进出的效果,能够通过在Mainfest.xml文件里设置主题的方式来实现.还能够使用java代码. 一.设置样式 先看看实现动画的样式: <style name=&qu ...

  9. android面试题2

    一.属于GLSurFaceView特性的是: 1.管理一个surface,这个surface就是一块特俗的内存.能直接排版到Android的视图view上. 2.管理一个EGL display,它能让 ...

  10. 真正理解javascript的五道题目.

    题目一: if (!("a" in window)) { var a = 1; } alert(a); 题目二: var a = 1, b = function a(x) { x ...