hdu_4718_The LCIS on the Tree(树链剖分+线段树合并)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4718
题意:给你一棵树,每个节点有一个值,然后任给树上的两点,问这两点的最长连续递增区间是多少
题解:先树链剖分,然后结合线段树的区间合并来搞,注意的是要记录递增和递减两个状态,因为线段树的区间都是从根到子节点,如果询问从子节点到子节点,那么就是一增一减
#include<cstdio>
#include<algorithm>
#define F(i,a,b) for(int i=a;i<=b;i++)
#define root 1,n,1
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
using namespace std;
const int N=1e5+;
int t,x,y,n,ic=,q,cnt,g[N],ed,nxt[N],v[N],a[N];
inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
//树链剖分----------------------------
int dep[N],sz[N],fa[N],hs[N],tid[N],top[N],idx,cot[N];
void dfs1(int u,int pre){
dep[u]=dep[pre]+,sz[u]=,fa[u]=pre,hs[u]=;
for(int i=g[u];~i;i=nxt[i]){
dfs1(v[i],u),sz[u]+=sz[v[i]];
if(sz[v[i]]>sz[hs[u]])hs[u]=v[i];
}
}
void dfs2(int u,int tp){
top[u]=tp,tid[u]=++idx,cot[tid[u]]=a[u];
if(hs[u])dfs2(hs[u],tp);
for(int i=g[u];~i;i=nxt[i])if(v[i]!=hs[u])dfs2(v[i],v[i]);
}
//线段树-------------------------------
int Rn[N<<],Ln[N<<],len[N<<],ml[N<<],Rl[N<<];
int Ll[N<<],dml[N<<],dRl[N<<],dLl[N<<]; inline void up(int rt,int li,int ri){
Ln[rt]=Ln[li],Rn[rt]=Rn[ri];
Ll[rt]=Ll[li],Rl[rt]=Rl[ri];
dLl[rt]=dLl[li],dRl[rt]=dRl[ri];
ml[rt]=max(ml[li],ml[ri]);
dml[rt]=max(dml[li],dml[ri]);
if(Rn[li]<Ln[ri]){//左右区间可以合并
ml[rt]=max(ml[rt],Rl[li]+Ll[ri]);
if(Rl[li]==len[li])Ll[rt]=Ll[li]+Ll[ri];
if(Rl[ri]==len[ri])Rl[rt]=Rl[li]+Rl[ri];
}
if(Rn[li]>Ln[ri]){
dml[rt]=max(dml[rt],dRl[li]+dLl[ri]);
if(dRl[li]==len[li])dLl[rt]=dLl[li]+dLl[ri];
if(dRl[ri]==len[ri])dRl[rt]=dRl[li]+dRl[ri];
}
} void build(int l,int r,int rt){
len[rt]=r-l+;
if(l==r){
Ln[rt]=Rn[rt]=cot[l],ml[rt]=Ll[rt]=Rl[rt]=;
dml[rt]=dLl[rt]=dRl[rt]=;
return;
}
int m=(l+r)>>;
build(ls),build(rs),up(rt,rt<<,rt<<|);
}
//将两个区间合并
inline void adt(int li,int ri,int rt){len[rt]=len[li]+len[ri],up(rt,li,ri);} int anson(int l,int r){
int ans=max(dml[l],ml[r]);
if(Ln[l]<Ln[r])return max(ans,dLl[l]+Ll[r]);
return ans;
} int query(int L,int R,int l,int r,int rt){
if(L==l&&R==r)return rt;
int m=(l+r)>>;
if(m>=R)return query(L,R,ls);
else if(m<L)return query(L,R,rs);
else{
int lss=query(L,m,ls),rss=query(m+,R,rs);
adt(lss,rss,++cnt);
return cnt;
}
} int lca(int x,int y){
if(x==y)return ;
cnt=N<<;
int xp=-,yp=-,op;
while(top[x]!=top[y]){
if(dep[top[x]]>dep[top[y]]){
op=query(tid[top[x]],tid[x],root),x=fa[top[x]];
if(xp==-)xp=op;
else adt(op,xp,++cnt),xp=cnt;
}else{
op=query(tid[top[y]],tid[y],root),y=fa[top[y]];
if(yp==-)yp=op;
else adt(op,yp,++cnt),yp=cnt;
}
}
if(dep[x]>=dep[y]){
op=query(tid[y],tid[x],root);
if(xp==-)xp=op;
else adt(op,xp,++cnt),xp=cnt;
}else{
op=query(tid[x],tid[y],root);
if(yp==-)yp=op;
else adt(op,yp,++cnt),yp=cnt;
}
if(xp==-)return ml[yp];
if(yp==-)return dml[xp];
return anson(xp,yp);
} int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
F(i,,N-)g[i]=-;ed=;
F(i,,n)scanf("%d",a+i);
F(i,,n)scanf("%d",&x),adg(x,i);
dfs1(,),idx=,dfs2(,),build(root);
scanf("%d",&q);
printf("Case #%d:\n",ic++);
while(q--)scanf("%d%d",&x,&y),printf("%d\n",lca(x,y));
if(t)puts("");
}
}
hdu_4718_The LCIS on the Tree(树链剖分+线段树合并)的更多相关文章
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
随机推荐
- [折腾纪实]JAVA的坑
开贴记录使用JAVA踩的坑-- P.S. 学习编程最好的方法就是用一个贴心的IDE写,然后隔着屏幕都能感觉到IDE在骂自己SB-- Overridable method calls in constr ...
- css3选择器:nth-child和nth-of-type之间的差别
<section> <p>我是第1个p标签</p> <p>我是第2个p标签</p> </section> 然后对应2个选择器对应 ...
- OGG强制停止进程
1.异常现象[oracle@localhost ~]$ ggsci Oracle GoldenGate Command Interpreter for OracleVersion 11.1.1.0.0 ...
- ACdream 1083 人民城管爱人民
拓扑排序,然后从终点开始递推. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio ...
- 在家用机上搭建 Git https 服务器
今天主要叙述在家里台式机的虚拟机上搭建支持 https 的 ubuntu git 服务器. 实际上,从一个用户请求家里 git 服务器代码,最终完成代码的传输,主要是通过以下的过程: 首先,从外界寻找 ...
- jQuery切换网页皮肤并保存到Cookie示例代码
经过使用,靠谱! <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...
- 5-jQuery - AJAX get()/post()页面请求即执行
get 前台页面 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> &l ...
- CentOS7 安装 Mysql 服务
我希望所有的软件包都用 rpm.yum 安装,这样卸载.升级.管理方便,可是自带的 yum 仓库里面没有 mysql-server 或者不是最新的,我需要安装MySQL官方的 yum 仓库, http ...
- $_SERVER 等超全局数组的用法 $_COOKIE $_GET $_SESSION
$_SERVER 服务器和执行环境信息 例如 $_SERVER['SERVER_NAME']; 当前运行脚本所在的服务器的主机名.如果脚本运行于虚拟主机中,该名称是由那个虚拟主机所设置的值决定.$_G ...
- 4、Web应用程序中的安全向量 -- over-posting(重复提交)
模型绑定是ASP.NET MVC提供的强大功能,可遵照命名约定将输入元素映射到模型属性,从而极大地简化了处理用户输入的过程,然而,这也成为了攻击的另一种没接,给攻击者提供了一个填充模型属性的机会,右下 ...