poj3237(树链剖分)
题目链接: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(树链剖分)的更多相关文章
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- poj3237树链剖分边权+区间取负
树链剖分+线段树lazy-tag在树链上操作时千万不要写错.. /* 树链剖分+线段树区间变负 */ #include<iostream> #include<cstring> ...
- poj3237 树链剖分 暴力
NEGATE a,b 将a b间的线段取反,这题应该用线段树+成段更新.我成段更新写的挫了,试了暴力修改过了(数据水). 也是简单的题目.不过要注意点和边的区别. #include<queue& ...
- 【POJ3237】Tree(树链剖分)
题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n& ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- Cogs 1583. [POJ3237]树的维护 LCT,树链剖分
题目:http://cojs.tk/cogs/problem/problem.php?pid=1583 1583. [POJ3237]树的维护 ★★★☆ 输入文件:maintaintree.in ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- [POJ3237]Tree解题报告|树链剖分|边剖
关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- 【POJ3237】【树链剖分】Tree
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- C++学习之路—继承与派生(三):多重继承与虚基类
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 多重继承是指一个派生类有两个或多个基类.例如,有 ...
- Net MVC微信扫码支付
微信扫码支付+Asp.Net MVC 这里的扫码支付指的是PC网站上面使用微信支付,也就是官方的模式二,网站是Asp.net MVC,整理如下. 一.准备工作 使用的微信API中的统一下单方法,关键的 ...
- UIPageControl的一个Demo
本篇文章只是记录了一个自定义UIPageControl 的制作,其实很简单的 源码在底部会奉上链接,还望多多交流,多多支持. 首先效果图如下: 首先先做一个UISCrollView // 建议这样 ...
- 输出特殊符号,可以用单引号'引文':echo 'Hello World !'
输出特殊符号,可以用单引号'引文':echo 'Hello World !'
- 医院API免费接口的公布
医院通网(http://hospital.yi18.net) 站点上站快两个月了,基本已经稳定,尽管还有非常多小bug,但还是不影响大局.抱着数据开放和共享的理念,医院大全API接口 (http:// ...
- 【ASP.NET Web API教程】5.1 HTTP消息处理器
原文:[ASP.NET Web API教程]5.1 HTTP消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 5.1 HTTP ...
- spring异常记录-----java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
今天在练习怎样SSH中进行单元測试的时候出现下列异常: SEVERE: Exception starting filter Struts2 java.lang.NoClassDefFoundError ...
- linux 配置 mail server
一.配置yum安装工具 ① 进入yum目录 [root@bj ~]# cd /etc/yum.repos.d ② 配置yum.repo [root@bj yum.repos.d]# cprhel- ...
- Apache Lucene
1.Lucene -全文搜索引擎 Apache Lucene 是一个基于Java的全文搜索引擎,利用它能够轻易的为Java软件添�全文搜索引擎的功能. Lucene最重要的工作是替文件的每个字索引, ...
- 在WPF的WebBrowser控件中抑制脚本错误
原文:在WPF的WebBrowser控件中抑制脚本错误 今天用WPF的WebBrowser控件的时候,发现其竟然没有ScriptErrorsSuppressed属性,导致其到处乱弹脚本错误的对话框,在 ...