F. Jumping Monkey II

题意:
给你 n = 2 e 5 n=2e5 n=2e5的一棵树,每个点有点权 a [ i ] < = 1 e 9 a[i]<=1e9 a[i]<=1e9,对于每个点,求以这个点出发,并且以自己为 L I S LIS LIS 的起点 的 最长 L I S LIS LIS的长度。

思路:
首先假设一号结点为根,然后每个点作为LIS的起点有三种可能:

标注 s t st st的结点为 L I S LIS LIS的起点,直线向上代表走父亲,向下代表走子树。
圆圈的点,是在 L I S LIS LIS上的点,不在 L I S LIS LIS上的点没有画出,用直线表示。

情况一:子树的结点做贡献
情况二:祖先结点和子树不做贡献,从除子树和祖先结点转移过来
情况三:祖先结点做贡献,从祖先结点转移过来

对于情况一,我们需要在子树里找点权比当前点大,且 向下的 L I S LIS LIS最长的 转移过来。
对于情况二,我们需要在除子树和除祖先结点里找点权比当前点大,且 向下的 L I S LIS LIS最长的 转移过来。
考虑这两个一起做,点权比当前点大的限制比较难处理,所以考虑按照点权从大到小加点,并用线段树维护。
对于情况一,就可以用 d f s dfs dfs序求子树 查询最大值转移过来。(为了下面的情况三,这里每个点需要求出向下的最大长度和次大长度,并且记一下最大长度是哪个子树转移过来的。)
对于情况二,就可以利用 树剖序 求不在当前向上的重链以及子树的 最大值转移过来。

现在只需要考虑情况三,可以发现每个祖先 f a fa fa 有 三种选择:
第一种: 从 f a fa fa的祖先转移过来;
第二种:不从 f a fa fa的祖先且不从子树转移过来,即其他部分转移过来;
第三种: 从 f a fa fa的子树转移过来,但是子树不和当前 结点 x x x的子树重合;

然后每个点可以从祖先中点权比自己大的最大值转移过来。
这里就不能从大到小加点了,因为有子树不能重合的限制,考虑 d f s dfs dfs的过程中 用线段树维护 当前结点到根的路径上的信息。用排序过后的标号来建线段树,就可以用区间查询最大值 来实现 求点权比自己大的最大值了。

详细细节见代码。
只能说跑的飞快:

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n,m) for(int i=n;i<=m;i++)
#define repp(i,n,m) for(int i=n;i>=m;i--)
const int N= 2e5+10;int n,m,t;
vector<int>v[200050],vv;
struct nod{int x,id;
}z[200050];
int dfn[200050],siz[200050];
int len=0;int tr[2][800050];
#define ls p<<1
#define rs p<<1|1
#define mid (l+r>>1)
int ans[200005];
int dep[200059],fa[200050],top[200050],son[200050];
int dp[200050][2],id[200050];
int idd[200050],st[200050],ed[200060];void dfs1(int x,int pre){fa[x]=pre;dep[x]=dep[pre]+1;siz[x]=1;son[x]=0;for(auto to:v[x]){if(to==pre)continue;dfs1(to,x);siz[x]+=siz[to];if(siz[to]>=siz[son[x]])son[x]=to;}
}
void dfs2(int x,int pre){if(son[pre]==x)top[x]=top[pre];else top[x]=x;dfn[x]=++len;if(son[x])dfs2(son[x],x);for(auto to:v[x]){if(to==pre||to==son[x])continue;dfs2(to,x);}
}
bool cmp(nod a,nod b){return a.x>b.x;
}
void build(int p,int l,int r,int op){tr[op][p]=0;if(l==r)return;build(ls,l,mid,op);build(rs,mid+1,r,op);
}
void update(int p,int l,int r,int x,int w,int op){if(l==r){tr[op][p]=w;return;}if(x<=mid)update(ls,l,mid,x,w,op);else update(rs,mid+1,r,x,w,op);tr[op][p]=max(tr[op][ls],tr[op][rs]);
}
int query(int p,int l,int r,int x,int y,int op){if(x>y)return 0;if(x<=l&&r<=y){return tr[op][p];}int ans=0;if(x<=mid)ans=max(ans,query(ls,l,mid,x,y,op));if(mid<y)ans=max(ans,query(rs,mid+1,r,x,y,op));return ans;
}
void up(int x,int y){int i=y;while(top[x]!=top[y]){int a=top[y];int b=y;ans[i]=max(ans[i],query(1,1,n,dfn[b]+siz[b],dfn[a]+siz[a]-1,0)+1);y=fa[top[y]];ans[i]=max(ans[i],query(1,1,n,dfn[y]+1,dfn[a]-1,0)+1);ans[i]=max(ans[i],query(1,1,n,dfn[a]+siz[a],dfn[y]+siz[y]-1,0)+1);}int a=top[y];int b=y;ans[i]=max(ans[i],query(1,1,n,dfn[b]+siz[b],dfn[a]+siz[a]-1,0)+1);
}
void dfs3(int x,int pre){int res=query(1,1,n,1,st[z[idd[x]].x]-1,1)+1;ans[x]=max(ans[x],res);update(1,1,n,idd[x],max(res,max(ans[x],dp[x][1])),1);if(id[x]!=-1)dfs3(v[x][id[x]],x);update(1,1,n,idd[x],max(res,max(ans[x],dp[x][0])),1);for(int i=0;i<v[x].size();i++){int to=v[x][i];if(i==id[x]||to==pre)continue;dfs3(to,x);}update(1,1,n,idd[x],0,1);
}
int main(){scanf("%d",&t);while(t--){scanf("%d",&n);len=0;vv.clear();for(int i=1;i<=n;i++){scanf("%d",&z[i].x);z[i].id=i;vv.push_back(z[i].x);ans[i]=0;}sort(vv.begin(),vv.end());vv.erase(unique(vv.begin(),vv.end()),vv.end());for(int i=1;i<=n;i++){z[i].x=lower_bound(vv.begin(),vv.end(),z[i].x)-vv.begin()+1; }for(int i=1;i<n;i++){int a,b;scanf("%d%d",&a,&b);v[a].push_back(b);v[b].push_back(a);}build(1,1,n,0);build(1,1,n,1);dfs1(1,0);dfs2(1,0);sort(z+1,z+1+n,cmp);for(int i=1;i<=n;i++){if(z[i].x!=z[i-1].x)st[z[i].x]=i;ed[z[i].x]=i;idd[z[i].id]=i;}ll pre=1;rep(i,1,n){if(z[i].x!=z[pre].x){while(pre<i){update(1,1,n,dfn[z[pre].id],dp[z[pre].id][0],0);pre++;}}dp[z[i].id][0]=1;dp[z[i].id][1]=-1e9;id[z[i].id]=-1;int cnt=-1;for(auto to:v[z[i].id]){cnt++;if(to==fa[z[i].id])continue; int res=query(1,1,n,dfn[to],dfn[to]+siz[to]-1,0);if(res+1>dp[z[i].id][0]){dp[z[i].id][1]=dp[z[i].id][0];dp[z[i].id][0]=res+1;id[z[i].id]=cnt;}else if(res+1>dp[z[i].id][1]){dp[z[i].id][1]=res+1;}}up(1,z[i].id);}dfs3(1,0);for(int i=1;i<=n;i++)printf("%d\n",max(ans[i],dp[i][0]));vv.clear();for(int i=1;i<=n;i++)v[i].clear();}return 0;
}

2021 Jiangsu Collegiate Programming Contest F. Jumping Monkey II 树剖+线段树相关推荐

  1. 2021 Jiangsu Collegiate Programming Contest部分题解

    2021 Jiangsu Collegiate Programming Contest 目录 A. Spring Couplets C. Magical Rearrangement I. Fake W ...

  2. 「团队训练赛」2021 Jiangsu Collegiate Programming Contest题解

    A - Spring Couplets 题目描述: 写春联,满足所需的平仄关系 如果上联的一个字是平的,那下联对应的字必须是仄的 相同的,如果上联的一个字是仄的,那下联对应的字必须是平的 而且上联的最 ...

  3. 2021 Jiangsu Collegiate Programming Contest——K. Longest Continuous 1

    题目地址https://codeforces.com/gym/103495/problem/K 题目解析 题目 思路 代码 题目 Example: 4 1 2 3 4 output: 0 1 2 2 ...

  4. 2018 ACM-ICPC, Syrian Collegiate Programming Contest F. Pretests(子集dp)

    LINK 题意 一道题有kkk个测试点,共提交了nnn次 每次提交是一个长为kkk的010101串,表示是否能通过第iii个测试点 现在要求你重新排序kkk个测试点,使得∑i=1nw[i]\sum\l ...

  5. 2022 Jiangsu Collegiate Programming Contest - J. Balanced Tree

    L. Collecting Diamonds 题目描述 A binary tree T is called super balanced if T is empty or satisfies the ...

  6. 2020 Jiangsu Collegiate Programming Contest

    比赛链接 题号 题目 难易 考点 Gym 102875A Array 难 线段树,欧拉降幂 Gym 102875B Building Blocks Gym 102875C Cats 签到题 贪心,思维 ...

  7. 2017 ACM Arabella Collegiate Programming Contest F. Monkeying Around GYM101350F

    对单个点考虑 实际上每个点的结果只被最后的那种操作影响 那么处理一下每个点对应的最后一个操作种类 然后对每个种类都和对应的点都检查一下是否被操作了2次 转化成n个点 m个区间 多少点被覆盖>=2 ...

  8. 2022 Jiangsu Collegiate Programming Contest I. Cutting Suffix

    题目链接 Examples input aa Output 1 input ab Output 0 题目大意: 后缀i是字符串从第i个字符开始到最后的字符字串 定义Wi,j是字符串 后缀i和后缀j的公 ...

  9. 2021 HZNU Winter Training Day 17 (2018 German Collegiate Programming Contest (GCPC 18))

    2021 HZNU Winter Training Day 17 (2018 German Collegiate Programming Contest (GCPC 18)) 题目 A B C D E ...

最新文章

  1. 在 Visual Basic .NET 或 JScript 代码中使用早期绑定
  2. 一、稀疏数组的实际应用和代码实现
  3. 使用VC来操作Excel表格的源码
  4. MVC之实体框架(数据持久化框架)EntityFrameWork(EF)
  5. centos/Linux 解决使用sudo命令时xxx is not in the sudoers file.This incident will be reported
  6. 使用vue创建自己的项目
  7. Nagios 分布式
  8. c++把字符串逆序输出
  9. 表格识别综述与相关实战
  10. Matlab中mat2str函数使用
  11. 简单说一下Flutter框架
  12. Solve TSP with dynamic programming——动态规划解决旅行商(邮递员)问题
  13. 【C++】1014 福尔摩斯的约会
  14. 2022-2028年全球与中国光谱比色计行业市场深度调研及投资预测分析
  15. 网络猫只有计算机和机顶盒两个口,电信的猫上有两个网口,但是只能用网口1,这是为什么。360......
  16. filebeat+logstash日志采集Invalid version of beats protocol错误
  17. SSD的SLC MLC 和TLC哪个好?
  18. if…if…和if…else if的区别是什么?
  19. 去律师面试python_律所面试应该怎样准备?
  20. 一阶RC低通滤波算法原理与实现

热门文章

  1. 低通、高通数字滤波器——C语言单片机实现
  2. Unity实现模型外发光效果HighlightingSystem插件解析
  3. matlab解矩阵方程组
  4. 关于SurfaceHolder.addCallback方法无法调用surfaceCreated 方法不回调的一个建议
  5. 同位素的物理性质及蛋白质组学应用
  6. 使用postMessage的踩坑记录,解决postMessage的监听事件多次触发
  7. 传统语音增强——基本的维纳滤波语音降噪算法
  8. 江浙沪计算机专业学校排名,中国高校TOP100排名出炉,全国211大学考研难度分析...
  9. 如何实现直接执行源代码
  10. golang力扣leetcode 297.二叉树的序列化与反序列化