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 :把某个节点 ...
随机推荐
- Android实现动画循环的方式
每次想到循环播放.重复执行时,脑海中总是冒出在while(true)的实现方式. Thread thread = new Thread(new Runnable(){ public void run( ...
- JMM内存管理
原文地址http://www.cnblogs.com/BangQ/p/4045954.html 原本准备把内存模型单独放到某一篇文章的某个章节里面讲解,后来查阅了国外很多文档才发现其实JVM内存模型的 ...
- 《精通CSS》——个人总结
[属性选择器] 属性选择器可以根据某个属性是否存在或属性的值来寻找元素. 只有在规定了 !DOCTYPE 时,IE7 和 IE8 才支持属性选择器.在 IE6 及更低的版本中,不支持属性选择. 事例: ...
- wordpress建站过程5——footer.php
footer中写的就只有网站地图,公司信息等等简单东西而已: <?php wp_footer(); ?> <div class="footer"> < ...
- DOM对象和JQuery有什么不同的地方?
jQuery对象和DOM对象使用说明,需要的朋友可以参考下.1.jQuery对象和DOM对象第一次学习jQuery,经常分辨不清哪些是jQuery对象,哪些是 DOM对象,因此需要重点了解jQuery ...
- 【第五篇】androidEventbus源代码阅读和分析之发送粘性事件和接收粘性事件代码分析
代码里面发送粘性事件代码如下: // 发送Sticky事件 EventBus.getDefault().postSticky(new User("soyoungboy", &quo ...
- 4、js内置函数
前言:上一篇我介绍了函数的基本概念,和一些简单的Demo.其实很多函数是js内置的,我们无需自己去写,直接拿过来用即可.内置函数分为全局函数和js内置对象的函数区别:全局函数不属于任何一个内置对象.理 ...
- 二、WCF应用的通信过程
注:本文为学习摘抄,原文地址:http://www.cnblogs.com/iamlilinfeng/archive/2012/09/26/2703759.html 一.概述 WCF能够建立一个跨平台 ...
- Arch安装fcitx输入法
安装fcitx,安装gtk.qt模块. [root@ARCH ~]# pacman -S fcitx-im :: There are 4 members in group fcitx-im: :: R ...
- jQuery 属性操作 - attr() 方法
定义和用法 attr() 方法设置或返回被选元素的属性值. 根据该方法不同的参数,其工作方式也有所差异. 实例1 设置被选元素的属性和值. <html><head><sc ...