大意: 给定树, 每个点有点权, 求最长非减树链, 满足树链上最大值与最小值之差不超过D

点分治, 线段树维护最小值为$x$时的最长非增和非减树链即可.

实现时有技巧是翻转一下儿子区间, 这样可以只维护一种树链, 时间复杂度$O(nlog^2n)$, 空间复杂度$O(n)$.

要注意使用线段树要注意每次清空, 不清空的话内存会卡到$O(nlog^2n)$

看其他dala0的题解好像说可以用set来维护, 但不是很懂要怎么用set区间更新最值.

#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <string.h>
#include <queue>
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define pb push_back
#define mid ((l+r)>>1)
#define lc tr[o].l
#define rc tr[o].r
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
using namespace std; const int N = 1e5+10, INF = 0x3f3f3f3f;
int n, rt, sum, ans, D, tot, T;
int a[N], vis[N];
int mx[N], sz[N];
vector<int> g[N];
struct {
int l,r,mx;
} tr[N<<2]; void getrt(int x, int fa) {
mx[x]=0, sz[x]=1;
for (int y:g[x]) if (!vis[y]&&y!=fa) {
getrt(y,x);sz[x]+=sz[y];
mx[x]=max(mx[x],sz[y]);
}
mx[x]=max(mx[x],sum-sz[x]);
if (mx[rt]>mx[x]) rt=x;
} void query(int o, int l, int r, int ql, int qr, int c) {
if (!o) return;
if (ql<=l&&r<=qr) return ans = max(ans, tr[o].mx+c),void();
if (mid>=ql) query(ls,ql,qr,c);
if (mid<qr) query(rs,ql,qr,c);
}
void update(int &o, int l, int r, int x, int v) {
if (!o) o=++tot;
tr[o].mx = max(tr[o].mx, v);
if (l==r) return;
if (mid>=x) update(ls,x,v);
else update(rs,x,v);
} void dfs_lis(int x, int fa, int d) {
if (a[x]<a[fa]) return;
query(T,1,N,a[x]-D,a[x],1+d);
for (int y:g[x]) if (!vis[y]&&y!=fa) {
dfs_lis(y,x,d+1);
}
}
void dfs_lds(int x, int fa, int d) {
if (a[x]>a[fa]) return;
update(T,1,N,a[x],d);
for (int y:g[x]) if (!vis[y]&&y!=fa) {
dfs_lds(y,x,d+1);
}
}
void calc(int x, vector<int> &g) {
while (tot) tr[tot].l=tr[tot].r=tr[tot].mx=0,--tot;
T = 0;
update(T,1,N,a[x],0);
//因为题目要求非减, 一条链可能既是LIS又是LDS
//这里先用LIS更新答案, 再更新LDS的值, 防止一条链同时处理两次
//同时为了防止全部都为LDS的情况, 最后再用LDS更新一次答案
//但是实际上本题数据比较水, 很多情况不考虑也能过
for (int y:g) {
dfs_lis(y,x,1);
dfs_lds(y,x,1);
}
query(T,1,N,a[x]-D,a[x],1);
}
void solve(int x) {
vis[x] = 1;
vector<int> son;
for (int y:g[x]) son.pb(y);
calc(x,son);
reverse(son.begin(),son.end());
calc(x,son);
for (int y:g[x]) if (!vis[y]) {
mx[rt=0]=n,sum=sz[y];
getrt(y,0),solve(rt);
}
} void work() {
scanf("%d%d", &n, &D);
REP(i,1,n) scanf("%d", a+i);
REP(i,1,n) g[i].clear(),vis[i]=0;
REP(i,2,n) {
int u, v;
scanf("%d%d", &u, &v);
g[u].pb(v),g[v].pb(u);
}
sum=mx[0]=n, getrt(1,0), solve(rt);
}
int main() {
int t;
scanf("%d", &t);
REP(i,1,t) {
ans = 1;
work();
printf("Case #%d: %d\n", i, ans);
}
}

LRIP UVALive - 7148 (点分治)的更多相关文章

  1. UVALive 7148 LRIP(树的分治+STL)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  2. UVALive 7148 LRIP【树分治+线段树】

    题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...

  3. UVALive 7148 LRIP 14年上海区域赛K题 树分治

    题意 n个点组成一棵树, 带有点权. 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D. 显然是树分治, 但是分治之后如何维护答案呢. 假设当前重心为g, 分别记录g出发不降路径的长度,以及 ...

  4. UVALive 7148 LRIP

    LRIPTime Limit: 10000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu 解题:树分治 参考了Oyking大神的解法 ...

  5. UvaLive 6667 Longest Chain (分治求三元组LIS&amp;树状数组)

    题目链接: here 题意: 和hdu4742类似.差别就是一部分三元组是直接给出的.另一部分是用他给的那个函数生成的.还有就是这里的大于是严格的大于a>b必须ax>bx,ay>by ...

  6. <算法竞赛入门经典> 第8章 贪心+递归+分治总结

    虽然都是算法基础,不过做了之后还是感觉有长进的,前期基础不打好后面学得很艰难的,现在才慢慢明白这个道理. 闲话少说,上VOJ上的专题训练吧:http://acm.hust.edu.cn/vjudge/ ...

  7. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  8. 树分治learning

    学习了树的点分治,树的边分治似乎因为复杂度过高而并不出众,于是没学 自己总结了一下 有些时候面对一些树上的结构 并且解决的是和路径有关的问题的时候 如果是多个询问 关注点在每次给出两个点,求一些关于这 ...

  9. 算法笔记--CDQ分治 && 整体二分

    参考:https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen 前置技能:树 ...

随机推荐

  1. 新版jquery的ajax调用 , jquery1.5以上

    原文出处:http://api.jquery.com/jQuery.ajax/,该链接页面底部有代码展示 示例1: $.ajax({ method: "POST", url: &q ...

  2. 【css flex】将多个<div>放在同一行

    使用style里的flex属性 默认情况下,一个div独占一行 使用css选择器给外层div加上以下flex属性,则该div的子div可以在同一行中显示, .runs-paginator-flex-c ...

  3. MVC4中使用Html.DropDownList实现级联

    本文记录了一个在MVC4中使用PartialView实现级联效果的小例子. 准备工作 首先准备一下要级联的数据,新建两个类:Province和City public class Province { ...

  4. IntelliJ IDEA 、PyCharm、WebStorm、PhpStorm等JetBrains公司软件 激活的License Server本地搭建教程

    一.背景 IntelliJ IDEA是JetBrains公司的一款IDE,主要用于java开发,可以编写Java.Groovy.Kotlin.Scala等语言,也可以直接做Android开发. 同系列 ...

  5. 【Python】sasa版:文件中csv读取在写入csv读取的数据和执行是否成功。

    sasa写的文件(包含解析文字) # coding=utf- from selenium import webdriver from time import sleep import keyword ...

  6. 002-spring cache 基于声明式注解的缓存-01-Cacheable annotation

    一.简述 对于缓存声明,抽象提供了一组Java注解: @Cacheable触发缓存填充(这里一般放在创建和获取的方法上) @CacheEvict触发缓存驱逐(用于删除的方法上) @CachePut更新 ...

  7. 006-线程同步解决【ReentrantLock】

    一.解决方案 004-线程同步问题引出.同步问题解决.死锁.生产者与消费者 通过以上文章可知,通过原子性AtomicLong .以及内部锁(synchronized)机制可以解决线程安全问题.以下是一 ...

  8. Checkpoint的运行原理和源码实现

    引言 Checkpoint 到底是什么和需要用 Checkpoint 解决什么问题: Spark 在生产环境下经常会面临 Transformation 的 RDD 非常多(例如一个Job 中包含1万个 ...

  9. (转) 密码学中的“盐值 Salt”

    为什么要在密码里加点“盐” 盐(Salt) 在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”. 以上这句话是维基百科上对于 ...

  10. oracle 查询按月份分组

    如下表table1: 日期(exportDate)               数量(amount) --------------                    ----------- 14- ...