HDU 4718 The LCIS on the Tree(树链剖分)
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.
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.
Then output Q lines, each with an answer to the query.
There should be a blank line *BETWEEN* each test case.
#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(树链剖分)的更多相关文章
- hdu_4718_The LCIS on the Tree(树链剖分+线段树合并)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4718 题意:给你一棵树,每个节点有一个值,然后任给树上的两点,问这两点的最长连续递增区间是多少 题解: ...
- HDU 5614 Baby Ming and Matrix tree 树链剖分
题意: 给出一棵树,每个顶点上有个\(2 \times 2\)的矩阵,矩阵有两种操作: 顺时针旋转90°,花费是2 将一种矩阵替换为另一种矩阵,花费是10 树上有一种操作,将一条路经上的所有矩阵都变为 ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- HDU 5044 Tree --树链剖分
题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...
- HDU 3966:Aragorn's Story(树链剖分)
http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:有n个点n-1条边,每个点有一个权值,有两种操作:询问一个点上权值是多少和修改u到v这条链上的权值. ...
- 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 ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
随机推荐
- 已禁用对分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具启用 DTC 以便在 MSDTC 安全配置中进行网络访问。
今天写ASP.NET程序,在网页后台的c#代码里写了个事务,事务内部对一张表进行批量插入,对另外一张表进行查询与批量插入. 结果第二张表查询后foreach迭代操作时报错:已禁用对分布式事务管理器(M ...
- iOS Provisioning Profile(Certificate)与Code Signing详解
引言 关于开发证书配置(Certificates & Identifiers & Provisioning Profiles),相信做 iOS 开发的同学没少被折腾.对于一个 iOS ...
- 用CSS为表格添加边框
格式: <style type="text/css"> table tr td,th {border:1px solid #000;} </style>
- TCP协议中的三次握手和四次挥手
转自: http://blog.csdn.net/whuslei/article/details/6667471/ 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示:
- Stakeholder Risk Management
In this article we'll address the people swirling around your project: stakeholders. You'll find som ...
- windows7 密码保护 共享文件
windows7 密码保护 共享文件 2台windows7之间设置文件共享,本想使用ftp,但是配置指定用户连接,配置权限比较繁琐. 所以就想到使用window7的文件共享,并设置密码,共享整个硬盘的 ...
- LogBack配置详解(一)
一:根节点<configuration>包含的属性: scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true. scanPeriod: 设置监测配置文 ...
- sqlserver多表连接更新
一.MS SQL Server 多表关联更新 sql server提供了update的from 子句,可以将要更新的表与其它的数据源连接起来.虽然只能对一个表进行更新,但是通过将要更新的表与其它的数据 ...
- iOS:抽屉侧滑动画两种形式(1、UIView侧滑 2、ViewController侧滑)
前言: 在iOS中抽屉动画是很常用的一种技术,使用它有很炫的体验效果,为app增添特色,形式就两种,一个是UIView的侧滑,另一个就是ViewController的侧滑. 实现方式: 抽屉侧滑动画有 ...
- 使用weave实现跨主机docker容器互联
关于weave的原理不做细致的说明,如果想了解weave可以登陆官网:https://www.weave.works/ In this post,使用阿里云3台ECS服务器进行weave搭建,并测试搭 ...