LRIP
Time Limit: 10000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

解题:树分治

参考了Oyking大神的解法

我们用map<int,int>维护上升序列,first表示value,second表示长度,按first由小到大,second由大到小排列,因为在val相同的时候,当然是越长越好,但是,Oyking大神说过的冗余上升序列,意思就是在你的值比他小,长度也比它小,那么在拼接那个下降的序列的时候,就会导致极差大,所以可以删除这些没用的。

我们在搜索下降序列的时候,可以对map进行lower_bound,找出极差范围内最大的长度,进行合并即可

 #include <bits/stdc++.h>
using namespace std;
const int maxn = ;
struct arc{
int to,next;
arc(int x = ,int y = -){
to = x;
next = y;
}
}e[maxn<<];
bool vis[maxn];
int head[maxn],val[maxn],D,ret,tot;
int sz[maxn],maxson[maxn];
map<int,int>up;
void add(int u,int v){
e[tot] = arc(v,head[u]);
head[u] = tot++;
}
void dfs(int u,int fa){
sz[u] = ;
maxson[u] = ;
for(int i = head[u]; ~i; i = e[i].next){
if(e[i].to == fa || vis[e[i].to]) continue;
dfs(e[i].to,u);
sz[u] += sz[e[i].to];
maxson[u] = max(maxson[u],sz[e[i].to]);
}
}
int FindRoot(int sum,int u,int fa){
int ret = u;
maxson[u] = max(maxson[u],sum - sz[u]);
for(int i = head[u]; ~i; i = e[i].next){
if(e[i].to == fa || vis[e[i].to]) continue;
int x = FindRoot(sum,e[i].to,u);
if(maxson[x] < maxson[ret]) ret = x;
}
return ret;
}
void dfs_down(int u,int fa,int len){
auto it = up.lower_bound(val[u] - D);
if(it != up.end()) ret = max(ret,it->second + + len);
for(int i = head[u]; ~i; i = e[i].next){
if(e[i].to == fa || vis[e[i].to] || val[e[i].to] < val[u]) continue;
dfs_down(e[i].to,u,len + );
}
}
void insert(int val,int len){
auto x = up.lower_bound(val);
if(x != up.end() && x->second >= len) return;
auto ed = up.upper_bound(val);
auto it = map<int,int>::reverse_iterator(ed);
while(it != up.rend() && it->second <= len) ++it;
up.erase(it.base(),ed);
up[val] = len;
}
void dfs_up(int u,int fa,int len){
insert(val[u],len);
for(int i = head[u]; ~i; i = e[i].next){
if(e[i].to == fa || vis[e[i].to] || val[e[i].to] > val[u]) continue;
dfs_up(e[i].to,u,len + );
}
}
void work(int u,vector<int>&son){
up.clear();
up[val[u]] = ;
for(int v:son){
if(val[v] >= val[u]) dfs_down(v,,);
if(val[v] <= val[u]) dfs_up(v,,);
}
}
void solve(int u){
dfs(u,);
int root = FindRoot(sz[u],u,);
vis[root] = true;
vector<int>son;
for(int i = head[root]; ~i; i = e[i].next)
if(!vis[e[i].to]) son.push_back(e[i].to);
work(root,son);
reverse(son.begin(),son.end());
work(root,son);
for(int i = head[root]; ~i; i = e[i].next)
if(!vis[e[i].to]) solve(e[i].to);
}
int main(){
int kase,n,u,v,cs = ;
scanf("%d",&kase);
while(kase--){
scanf("%d %d",&n,&D);
memset(head,-,sizeof head);
memset(vis,false,sizeof vis);
tot = ;
for(int i = ; i <= n; ++i)
scanf("%d",val + i);
for(int i = ret = ; i < n; ++i){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
solve();
printf("Case #%d: %d\n",cs++,ret);
}
return ;
}

UVALive 7148 LRIP的更多相关文章

  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. LRIP UVALive - 7148 (点分治)

    大意: 给定树, 每个点有点权, 求最长非减树链, 满足树链上最大值与最小值之差不超过D 点分治, 线段树维护最小值为$x$时的最长非增和非减树链即可. 实现时有技巧是翻转一下儿子区间, 这样可以只维 ...

  5. UVALive - 4108 SKYLINE[线段树]

    UVALive - 4108 SKYLINE Time Limit: 3000MS     64bit IO Format: %lld & %llu Submit Status uDebug ...

  6. UVALive - 3942 Remember the Word[树状数组]

    UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...

  7. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  8. 思维 UVALive 3708 Graveyard

    题目传送门 /* 题意:本来有n个雕塑,等间距的分布在圆周上,现在多了m个雕塑,问一共要移动多少距离: 思维题:认为一个雕塑不动,视为坐标0,其他点向最近的点移动,四舍五入判断,比例最后乘会10000 ...

  9. UVALive 6145 Version Controlled IDE(可持久化treap、rope)

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

随机推荐

  1. 题解报告:NYOJ #737 石子合并(一)(区间dp)

    描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...

  2. Harris角点检测原理及实现

    一.原理 二.实现 close all; clear all; I=imread('test.tif'); [posX,posY]=harris(I); figure;imshow(I); hold ...

  3. css新奇技术及其未来发展

    1.图像替换技术: 图像替换技术是指使用图像替换页面中文本的功能,类似与在页面中插入图像,只是这种方法更为方便,易于代码管理.通常来说,设计者习惯使用有意义的图像去替换一些标题,logo和某些特定的页 ...

  4. 504 Base 7 七进制数

    给定一个整数,将其转化为7进制,并以字符串形式输出.示例 1:输入: 100输出: "202" 示例 2:输入: -7输出: "-10"注意: 输入范围是 [- ...

  5. MySQL防止重复插入记录SQL

    INSERT INTO sysuser(') DUAL:表示虚拟表 sysuser:表名称

  6. 将php数组传递到js—json_encode(),json_decode()

    json_decode(),对一个json字符串进行解码,json_encode()是生成一个json字符串 上面的解释很清楚了,关于php里数组赋值的问题,列举如下: <?php //对象 c ...

  7. P1320 压缩技术(续集版)

    题目描述 设某汉字由N X N的0和1的点阵图案组成,如下图.我们依照以下规则生成压缩码.连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从上到下,由左到右.第一个数表示连续有几个0 ...

  8. 使用kubeadm安装kubernetes v1.14.1

    使用kubeadm安装kubernetes v1.14.1 一.环境准备 操作系统:Centos 7.5 ​ ⼀ 一台或多台运⾏行行着下列列系统的机器器: ​ Ubuntu 16.04+ ​ Debi ...

  9. 如何正确理解和使用 Activity的4种启动模式

    关于Activity启动模式的文章已经很多,但有的文章写得过于简单,有的则过于注重细节,本文想取一个折中,只关注最重要和最常用的概念,原理和使用方法,便于读者正确应用. Activity的启动模式有4 ...

  10. php bz2扩展安装

    php bz2扩展安装 2017年09月22日 14:14:36 Cookie_1030 阅读数:1781   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn ...