题目连接: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(树链剖分+线段树合并)的更多相关文章

  1. 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 ...

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

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

  3. POJ3237 Tree 树链剖分 线段树

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

  4. 【CF725G】Messages on a Tree 树链剖分+线段树

    [CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...

  5. 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, ...

  6. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

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

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

  9. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  10. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

随机推荐

  1. 寒假学干货之------ 初学者关于fragment_main(碎片的困扰)

    我们在activity_main中编写的框架,会被fragment_main中的取代掉,是因为新版的ADT为了配合平板Android3.0开发 起作用的代码在MainActivity.java中 pa ...

  2. jquery学习笔记2——jq效果

    一.显示隐藏: 可以使用show()和hide()方法来显示隐藏: $("#hide").click(function(){ $("p").hide(); }) ...

  3. Java中获取当前日期

    java.util.Date date = new Date();java.Text.SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd ...

  4. SDK平台三态按钮的实现

    Windows平台提供了丰富的控件,但是在使用中我们不会使用它提供的默认风格,有时候需要对控件进行改写,让它展现出更友好的一面,这次主要是说明三态按钮的实现. 三态按钮指的是按钮在鼠标移到按钮上时显示 ...

  5. 【MySQL】使用 Optimizer Trace 观察SQL执行过程

    Optimizer Trace 是MySQL 5.6.3里新加的一个特性,可以把MySQL Optimizer的决策和执行过程输出成文本.输出使用JSON格式,便于程序分析和人类阅读. 使用方法 1) ...

  6. redis 5 种数据结构

    常用命令 就DB来说,Redis成绩已经很惊人了,且不说memcachedb和tokyocabinet之流,就说原版的memcached,速度似乎也只能达到这个级别.Redis根本是使用内存存储,持久 ...

  7. php:跨域

    一个没那么难的历史难题,其实只要在被请求端,加一句: header('Access-Control-Allow-Origin: *'); 然后--然后没有了. //跨域访问的时候才会存在此字段 $or ...

  8. Linux性能监测:CPU篇(转)

    http://os.51cto.com/art/201012/239880.htm CPU 的占用主要取决于什么样的资源正在 CPU 上面运行,比如拷贝一个文件通常占用较少 CPU,因为大部分工作是由 ...

  9. Chapter 2 Open Book——27

    My assessment was confident. 我的评价是很自信的. "Prophase.""Do you mind if I look?" he a ...

  10. js--学习方法之2-转

    再说几点忠告 1,不要着急看一些复杂网页效果的代码,这样除了打击你自信心,什么也学不到.没达到一定的武功水平,割了小JJ也学不会葵花宝典的. 2,别急着加技术交流QQ群,加牛人QQ.如果你找张三丰交流 ...