Problem Description
For a sequence S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i <= j <= N and Si < Si+1 < Si+2 < ... < Sj-1 < Sj , then the sequence Si, Si+1, ... , Sj is a CIS(Continuous Increasing Subsequence). The longest CIS of a sequence is called the LCIS (Longest Continuous Increasing Subsequence).
Now we consider a tree rooted at node 1. Nodes have values. We have Q queries, each with two nodes u and v. You have to find the shortest path from u to v. And write down each nodes' value on the path, from u to v, inclusive. Then you will get a sequence, and please show us the length of its LCIS.
 
Input
The first line has a number T (T <= 10) , indicating the number of test cases.
For each test case, the first line is a number N (N <= 105), the number of nodes in the tree.
The second line comes with N numbers v1, v2, v3 ... , vN, describing the value of node 1 to node N. (1 <= vi <= 109)
The third line comes with N - 1 numbers p2, p3, p4 ... , pN, describing the father nodes of node 2 to node N. Node 1 is the root and will have no father.
Then comes a number Q, it is the number of queries. (Q <= 105)
For next Q lines, each with two numbers u and v. As described above.
 
Output
For test case X, output "Case #X:" at the first line.
Then output Q lines, each with an answer to the query.
There should be a blank line *BETWEEN* each test case.
 
题目大意:给你一棵树,每个点上有一个权值,Q个询问,问u到v的最短路径上的点权都取出来排成一排,这一段的LCIS是多少(最长连续上升子序列)。
思路:还算是比较裸的树链剖分,每条链用一个线段树来维护,不过要同时维护太多的东西难度有点高……反正不会有修改操作,果断把从某个点开始的LCIS等等改成了预处理……反正就是相当的麻烦……手欠开了一条麻烦得要死的题目……
 
代码(2062MS):
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAXV = ;
const int MAXE = MAXV;
const int MAXT = MAXV << ; int lmaxi[MAXT], rmaxi[MAXT], mmaxi[MAXT];
int lmaxd[MAXT], rmaxd[MAXT], mmaxd[MAXT];
int val[MAXV], n, m, T; int inc_ord[MAXV], dec_ord[MAXV], inc_rev[MAXV], dec_rev[MAXV]; void init_inc_dec() {
for(int i = , t = ; i <= n; ++i) {
if(t < i) t = i;
while(t < n && val[t] < val[t + ]) ++t;
inc_ord[i] = t - i + ;
}
for(int i = , t = ; i <= n; ++i) {
if(t < i) t = i;
while(t < n && val[t] > val[t + ]) ++t;
dec_ord[i] = t - i + ;
}
for(int i = n, t = n; i > ; --i) {
if(t > i) t = i;
while(t > && val[t] < val[t - ]) --t;
inc_rev[i] = i - t + ;
}
for(int i = n, t = n; i > ; --i) {
if(t > i) t = i;
while(t > && val[t] > val[t - ]) --t;
dec_rev[i] = i - t + ;
}
} int queryI(int x, int l, int r, int a, int b) {
if(a <= l && r <= b) {
return mmaxi[x];
} else {
int ll = x << , rr = ll | , mid = (l + r) >> ;
int ans = ;
if(a <= mid) ans = max(ans, queryI(ll, l, mid, a, b));
if(mid < b) ans = max(ans, queryI(rr, mid + , r, a, b));
if(val[mid] < val[mid + ]) {
ans = max(ans, min(rmaxi[ll], mid - a + ) + min(lmaxi[rr], b - mid));
}
return ans;
}
} int queryD(int x, int l, int r, int a, int b) {
if(a <= l && r <= b) {
return mmaxd[x];
} else {
int ll = x << , rr = ll | , mid = (l + r) >> ;
int ans = ;
if(a <= mid) ans = max(ans, queryD(ll, l, mid, a, b));
if(mid < b) ans = max(ans, queryD(rr, mid + , r, a, b));
if(val[mid] > val[mid + ]) {
ans = max(ans, min(rmaxd[ll], mid - a + ) + min(lmaxd[rr], b - mid));
}
return ans;
}
} void maintainI(int x, int l, int r) {
int ll = x << , rr = ll | , mid = (l + r) >> ;
if(val[mid] < val[mid + ]) {
lmaxi[x] = lmaxi[ll] + (lmaxi[ll] == mid - l + ) * lmaxi[rr];
rmaxi[x] = rmaxi[rr] + (rmaxi[rr] == r - mid) * rmaxi[ll];
mmaxi[x] = max(rmaxi[ll] + lmaxi[rr], max(mmaxi[ll], mmaxi[rr]));
} else {
lmaxi[x] = lmaxi[ll];
rmaxi[x] = rmaxi[rr];
mmaxi[x] = max(mmaxi[ll], mmaxi[rr]);
}
} void maintainD(int x, int l, int r) {
int ll = x << , rr = ll | , mid = (l + r) >> ;
if(val[mid] > val[mid + ]) {
lmaxd[x] = lmaxd[ll] + (lmaxd[ll] == mid - l + ) * lmaxd[rr];
rmaxd[x] = rmaxd[rr] + (rmaxd[rr] == r - mid) * rmaxd[ll];
mmaxd[x] = max(rmaxd[ll] + lmaxd[rr], max(mmaxd[ll], mmaxd[rr]));
} else {
lmaxd[x] = lmaxd[ll];
rmaxd[x] = rmaxd[rr];
mmaxd[x] = max(mmaxd[ll], mmaxd[rr]);
}
} void build(int x, int l, int r) {
if(l == r) {
lmaxi[x] = rmaxi[x] = mmaxi[x] = ;
lmaxd[x] = rmaxd[x] = mmaxd[x] = ;
} else {
int ll = x << , rr = ll | , mid = (l + r) >> ;
build(ll, l, mid);
build(rr, mid + , r);
maintainI(x, l, r);
maintainD(x, l, r);
}
} int v[MAXV];
int fa[MAXV], son[MAXV], size[MAXV], tid[MAXV], top[MAXV], dep[MAXV];
int head[MAXV], ecnt, dfs_clock;
int to[MAXE], next[MAXE]; void init(int n) {
memset(head, -, (n + ) * sizeof(int));
ecnt = dfs_clock = ;
} void add_edge(int u, int v) {
to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
} void dfs_size(int u, int depth) {
size[u] = ; son[u] = ; dep[u] = depth;
int maxsize = ;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
dfs_size(v, depth + );
size[u] += size[v];
if(size[v] > maxsize) {
son[u] = v;
maxsize = size[v];
}
}
} void dfs_heavy_edge(int u, int ancestor) {
val[tid[u] = ++dfs_clock] = v[u];
top[u] = ancestor;
if(son[u]) dfs_heavy_edge(son[u], ancestor);
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(v == son[u]) continue;
dfs_heavy_edge(v, v);
}
} int query(int x, int y) {
int res = , maxx = , prex = , maxy = , prey = ;
while(top[x] != top[y]) {
if(dep[top[x]] > dep[top[y]]) {
int sz = dep[x] - dep[top[x]] + ;
int up_ans = min(inc_rev[tid[x]], sz);
int down_ans = min(dec_ord[tid[top[x]]], sz);
res = max(res, queryD(, , n, tid[top[x]], tid[x]));
if(prex && v[prex] >= v[x]) maxx = ;
res = max(res, up_ans + maxx);
maxx = down_ans + (sz == down_ans) * maxx;
prex = top[x];
x = fa[top[x]];
} else {
int sz = dep[y] - dep[top[y]] + ;
int up_ans = min(dec_rev[tid[y]], sz);
int down_ans = min(inc_ord[tid[top[y]]], sz);
res = max(res, queryI(, , n, tid[top[y]], tid[y]));
if(prey && v[prey] <= v[y]) maxy = ;
res = max(res, up_ans + maxy);
maxy = down_ans + (sz == down_ans) * maxy;
prey = top[y];
y = fa[top[y]];
}
}
if(dep[x] > dep[y]) {
int sz = dep[x] - dep[y] + ;
int up_ans = min(inc_rev[tid[x]], sz);
int down_ans = min(dec_ord[tid[y]], sz);
res = max(res, queryD(, , n, tid[y], tid[x]));
if(prex && v[prex] >= v[x]) maxx = ;
if(prey && v[prey] <= v[y]) maxy = ;
res = max(res, up_ans + maxx);
res = max(res, down_ans + maxy);
if(up_ans == sz) res = max(res, maxx + up_ans + maxy);
} else {
int sz = dep[y] - dep[x] + ;
int up_ans = min(dec_rev[tid[y]], sz);
int down_ans = min(inc_ord[tid[x]], sz);
res = max(res, queryI(, , n, tid[x], tid[y]));
if(prex && v[prex] >= v[x]) maxx = ;
if(prey && v[prey] <= v[y]) maxy = ;
res = max(res, down_ans + maxx);
res = max(res, up_ans + maxy);
if(up_ans == sz) res = max(res, maxx + up_ans + maxy);
}
return res;
} int main() {
scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d", &n);
init(n);
for(int i = ; i <= n; ++i) scanf("%d", &v[i]);
for(int i = ; i <= n; ++i) {
scanf("%d", &fa[i]);
add_edge(fa[i], i);
}
dfs_size(, );
dfs_heavy_edge(, );
build(, , n);
init_inc_dec();
printf("Case #%d:\n", t);
scanf("%d", &m);
while(m--) {
int u, v;
scanf("%d%d", &u, &v);
printf("%d\n", query(u, v));
}
if(t != T) puts("");
}
}

HDU 4718 The LCIS on the Tree(树链剖分)的更多相关文章

  1. hdu_4718_The LCIS on the Tree(树链剖分+线段树合并)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4718 题意:给你一棵树,每个节点有一个值,然后任给树上的两点,问这两点的最长连续递增区间是多少 题解: ...

  2. HDU 5614 Baby Ming and Matrix tree 树链剖分

    题意: 给出一棵树,每个顶点上有个\(2 \times 2\)的矩阵,矩阵有两种操作: 顺时针旋转90°,花费是2 将一种矩阵替换为另一种矩阵,花费是10 树上有一种操作,将一条路经上的所有矩阵都变为 ...

  3. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  4. POJ3237 Tree 树链剖分 边权

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

  5. HDU 5044 Tree --树链剖分

    题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...

  6. HDU 3966:Aragorn's Story(树链剖分)

    http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:有n个点n-1条边,每个点有一个权值,有两种操作:询问一个点上权值是多少和修改u到v这条链上的权值. ...

  7. HDU 5840 This world need more Zhu 树链剖分+暴力

    This world need more Zhu 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5840 Description As we all ...

  8. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  9. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

随机推荐

  1. http协议(转)

    主要还是为了存放状态码··· 剖析 HTTP 协议   目录 HTTP 概述 HTTP 消息结构 HTTP 请求 HTTP 响应 HTTP 状态码 参考 回到顶部 HTTP 概述 HTTP 是什么? ...

  2. (转) java 简单工厂模式(实现一个计算器)

    package com.simpleFactory; /** * 运算类 * @author Administrator * */ public class Operation { private d ...

  3. CC2540 USB DONGLE 使用 BTool 调试BLE 说明

    一.Btool软件界面介绍 首先您要将USBDONGLE插入电脑的USB口,然后打开双击打开Btool软件,打开后如下图所示: 在安装驱动的教程中,我们已经记住了我们的USB DONGLE的串口号,在 ...

  4. ngrok的使用

    windows的ngrok配置: 步骤一:下载ngrok http://pan.baidu.com/s/1jH0s8o2 步骤二:如果你的国外网址没被墙就直接使用cmd命令行使用. 国内ngrok配置 ...

  5. Android源码剖析之Framework层实战版(Ams管理Activity启动)

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 讲到实战,就不得不拿两个例子来说明,本篇想拿的是应用最广泛的两个:Ams和Wms,一个管理activ ...

  6. drop、 truncate 、 delete

    相同点: truncate和不带where子句的delete, 以及drop都会删除表内的数据     不同点: 1. truncate和 delete只删除数据不删除表的结构 drop语句将删除表的 ...

  7. JVM 常用配置

    JVM的配置,最常用的两个配置就是:-Xms512m –Xmx1024m -Xms设置JVM的初始化内存大小,-Xmx为最大内存大小,当突破这个值,将会报内存溢出,导致的原因有很多,主要是虚拟机的回收 ...

  8. C++ 安全字符串拼接

    #include <stdio.h> #include <stdint.h> #include <stdarg.h> #if defined(__GNUC__) # ...

  9. 设计模式:建造者模式(Builder)

    定   义:将一个复杂对象的构建与它的表示分离,使得同一构建过程可以创建不同的表示. 结构图: 产品类: class Product { //部件集合 List<string> parts ...

  10. EChars学习-2

    上海的echars学习 <html> <head> <meta charset="utf-8"> <meta http-equiv=&qu ...