题目大意:

给你两个大小相同的树但是形状不一定一样
叫你选出最大的子集,满足下面两个条件

  1. 在第一颗树上是一条链
  2. 在第二颗树上任意两个点都不是祖先关系

解题思路:

  1. 首先我们现在第二颗树上面把每个点的dfs序处理处理,那么就变成在第一颗树上面找到最长的一条链,链上点的dfs序区间都不相交,祖先关系的点会存在下图关系
  2. 那么最开始我们想的是二分最大长度然后每次都去维护固定长度的链,每次区间修改(区间覆盖),O(1)O(1)O(1)查询,但是是O(nlog2n)O(nlog^2n)O(nlog2n)过不来
  3. 优化:假如我们dfs到某个点我们假如我们发现长度为lenlenlen是可以那么我们就可以保存这个长度去维护滑动窗口类似!因为答案肯定不会比lenlenlen还短,维护短的没意义,那么这个长度就是单调递增的,那么这样就没二分了!!
  4. 时间复杂度O(nlogn)O(nlogn)O(nlogn)

AC代码:

线段树区间加,维护区间最大值!!
最大值为1就是不相交!!
重复覆盖就是2!!

#include <bits/stdc++.h>#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;template<typename T> void read(T &x) {x = 0;char ch = getchar();ll f = 1;while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {read(first);read(args...);
}using namespace std;
/*-----------------------------------------------------------------*/ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3fconst int N = 6e5 + 10;
const double eps = 1e-5;
typedef pair<int, int> PII;
int mx[N << 1];
int lazy[N << 1];
int dfn;struct edge {int nt, ne;
};int head[N];
edge ed[N];
int si;
PII seg[N];
int que[N];
int st, et;
int n;void init(int n) {dfn = 0;for(int i = 1; i <= n; i++) head[i] = 0;si = 0;
}void add(int u, int v) {ed[++si] = edge{v, head[u]};head[u] = si;
}void pushdown(int rt) {if(lazy[rt]) {lazy[rt << 1] += lazy[rt];mx[rt << 1] += lazy[rt];lazy[rt << 1 | 1] += lazy[rt];mx[rt << 1 | 1] += lazy[rt];lazy[rt] = 0;}
}void build(int l, int r, int rt) {if(l == r) {lazy[rt] = mx[rt] = 0;return ;}int mid = (l + r) / 2;build(l, mid, rt << 1);build(mid + 1, r, rt << 1 | 1);lazy[rt] = mx[rt] = 0;
}void upd(int l, int r, int L, int R, int val, int rt) {if(l >= L && r <= R) {mx[rt] += val;lazy[rt] += val;return ;}int mid = (l + r) / 2;pushdown(rt);if(mid >= L) upd(l, mid, L, R, val, rt << 1);if(mid < R) upd(mid + 1, r, L, R, val, rt << 1 | 1);mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
}void dfs1(int p, int fa) {dfn++;seg[p].first = dfn;for(int e = head[p]; e; e = ed[e].ne) {int np = ed[e].nt;if(np == fa) continue;dfs1(np, p);}seg[p].second = dfn;
}
int ans = 0;
void dfs2(int p, int fa) {int pp = -1;que[et++] = p;upd(1, n, seg[p].first, seg[p].second, 1, 1);if(mx[1] == 1) {ans = max(ans, et - st);//出现了更长的链更新答案} else {if(et - st > ans) {//否则维护长度为ans的队列pp = que[st++];upd(1, n, seg[pp].first, seg[pp].second, -1, 1);}}for(int e = head[p]; e; e = ed[e].ne) {int np = ed[e].nt;if(np == fa) continue;dfs2(np, p);} if(pp > 0) {upd(1, n, seg[pp].first, seg[pp].second, 1, 1);que[--st] = pp;}upd(1, n, seg[p].first, seg[p].second, -1, 1);et--;return ;
}vector<PII> G1;int main() {int t;read(t);while(t--) {st = et = 0;G1.clear();read(n);init(n);build(1, n, 1);for(int i = 1; i < n; i++) {int u, v;read(u,v);G1.push_back({u, v});}for(int i = 1; i < n; i++) {int u, v;read(u,v);add(u, v);add(v, u);}dfs1(1, 0);init(n);for(auto &e : G1) {add(e.first, e.second);add(e.second, e.first);}ans = 0;dfs2(1, 0);printf("%d\n",ans);}
}

线段树 ---- 线段树维护线段相加+滑动变长窗口 2021牛客多校第7场 F xay loves trees相关推荐

  1. 2019牛客多校第七场 F Energy stones 树状数组+算贡献转化模拟

    Energy stones 题意 有n块石头,每块有初始能量E[i],每秒石头会增长能量L[i],石头的能量上限是C[i],现有m次时刻,每次会把[s[i],t[i]]的石头的能量吸干,问最后得到了多 ...

  2. 2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)

    题目链接:点击查看 题目大意:给出两棵以点 111 为根节点的有根树,现在要求满足条件的最大集合: 在第一棵树中,集合内的任意两个点都必须满足祖先关系,即 uuu 是 vvv 的祖先或 vvv 是 u ...

  3. 线段树合并与分裂维护树上最长上升子序列 + 点分治删点 ---- 2021 牛客多校第一场 C - Cut the tree(详解)

    题目大意: 给你一个树,树上每个点都有一个权值valnodeval_{node}valnode​,路径(u,v)(u,v)(u,v) 上所有点按顺序有序序列,令f(u,v)f(u,v)f(u,v)是这 ...

  4. 2021牛客多校7 - xay loves monotonicity(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数字序列 aaa 和 010101 序列 bbb,需要执行 mmm 次操作,每次操作分为如下三种类型: 1 x y:修改 a[x]=ya[x]= ...

  5. 2020牛客多校第7场C-A National Pandemic[树链剖分+思维]

    题目大意 1.首先我们看一下操作1:实际上可以说成在所有位置上加上w−dist(x,y)w-dist(x,y)w−dist(x,y),因为dist(x,x)=0dist(x,x)=0dist(x,x) ...

  6. 线段树 ---- 2021牛客多校第一场 J Journey among Railway Stations [线段树维护区间可行性判断]

    题目链接 题目大意: 一段路上有 NNN 个点,每个点有一个合法时间段[ui,vi][u_i,v_i][ui​,vi​],相邻两个点有一个长度wiw_iwi​.有qqq次询问,每次询问,在 [ui,v ...

  7. 2021牛客多校1——J:Journey of Railway Stations(线段树)

    题面 题意: 一段路上有 N N N​​​​ 个火车站,每个火车站有一个合法时间段 [ u i , v i ] [u_i, v_i] [ui​,vi​]​​​​​,相邻两个火车站有一个长度 c o s ...

  8. 2021牛客多校4 - Tree Xor(线段树+异或区间拆分)

    题目链接:点击查看 题目大意:给出一棵 nnn 个点组成的树,每个点权的取值范围是 [li,ri][l_i,r_i][li​,ri​],每条边权代表的是两点的异或值,现在问这棵树有多少种有效赋值 题目 ...

  9. 2019牛客多校第七场E Find the median 权值线段树+离散化

    Find the median 题目链接: https://ac.nowcoder.com/acm/contest/887/E 题目描述 Let median of some array be the ...

最新文章

  1. ●洛谷P3688 [ZJOI2017]树状数组
  2. 【RxSwift】flatMapLatest、 Error事件中断序列
  3. 正则表达式 2. 单字符或
  4. Puppet基于Master/Agent模式实现LNMP平台部署
  5. Vaadin附加组件和Maven
  6. 前端学习(1707):前端系列javascript之promise
  7. 中小企业集群ntpd服务搭建
  8. 2017.10.11 network 网络扩容 思考记录
  9. 新型 Linux 病毒,脚本超 1000 行,功能复杂
  10. combing string
  11. spring配置文件中导入约束的详细步骤
  12. win10添加组策略命令
  13. 一座5g基站造价多少?
  14. 史上最难php,世界上最难的简单几何体 - 我为数学狂 - 简单学习网论坛_中高考学习交流论坛_中学生学习论坛 - Powered by phpwind...
  15. linux 查看内存 udimm rdimm,关于内存类型UDIMM、RDIMM、LRDIMM
  16. JDK对Http协议的Keep-Alive的支持,以JDK8为例
  17. JS判断当前页面是否在微信内打开
  18. AIX命令创建JFS2的LV及FS(非smitty交互模式)
  19. vs编译出现 0xC0000005
  20. Tesra超算网络,招募内测用户,可优先体验免费GPU算力!

热门文章

  1. MATLAB_size()和find(),有什么区别?
  2. 目标检测:Anchor-Free时代
  3. 基于相交线的双目平面SLAM
  4. 全面解读PyTorch内部机制
  5. 一文看懂自动驾驶关键技术
  6. 基于Python进行相机校准
  7. iOS 10道细节面试题
  8. scrapy_redis使用
  9. 在像Angular2这样的SPA应用中使用Google Analytics的方法
  10. C程序演示产生僵死进程的过程