大意: 给定树, 每个点有点权, 求最长非减树链, 满足树链上最大值与最小值之差不超过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);
}
}

最新文章

  1. [Java入门笔记] Java语言基础(三):运算符
  2. 深入理解Java中的final关键字
  3. HTML 列表详解
  4. UML简介
  5. Spring整合Hibernate。。。。
  6. pecl install imagick
  7. 关于DCMTK3.6.0源代码编译的总结
  8. Spring框架学习之第3节
  9. Windows下配置cygwin和ndk编译环境
  10. 【转】解析Java finally
  11. ibatis缓存初探(1)
  12. asp.net中一般处理程序中添加session
  13. HDU 3359 Kind of a Blur(高斯消元)
  14. reincarnation server
  15. JAVA To C++ Converter Cracked ( 破解版 )
  16. Flask知识点二
  17. 部署wcf出现的问题与解决方法
  18. Chapter 1 Securing Your Server and Network(14):限制功能——xp_cmdshell 和OPENROWSET
  19. docker私有镜像仓库搭建
  20. sftp无法连接问题

热门文章

  1. nginx 认证访问web
  2. T-SQL数据库备份
  3. pta 习题集5-17 哥尼斯堡的“七桥问题”
  4. 设计模式之&mdash;&mdash;Chain of Responsibility
  5. freemarker 判断写法
  6. Django之urls.py详解
  7. 学习Mysql的记录贴 记录的内容是 指令的试用
  8. 4.5 Routing -- Setting Up A Controller
  9. 对Java平台的理解
  10. SQL 根据条件取不同列中的值来排序