Codeforces1083CMaxMex
作者:吻过彩虹的脸_378 | 来源:互联网 | 2024-09-25 19:57
Description一棵\(N\)个节点的树,每个节点上都有互不相同的\([0,~N-1]\)的数。定义一条路径上的数的集合为\(S\),求一条路径使得\(Mex(S)\)最大。
Description 一棵\(N\) 个节点的树, 每个节点上都有 互不相同的 \([0, ~N-1]\) 的数。
定义一条路径上的数的集合为 \(S\) , 求一条路径使得 \(Mex(S)\) 最大。
带修改, \(M\) 次查询
Solution 用一棵权值线段树维护。
节点 \([L,R]\) 存储信息:是否有一条路径包含 \([L,R]\) 内的所有数 以及 路径两个端点。
合并两个区间: 在\(4\) 个点中 枚举新路径的端点, 然后判断另外两个点是否在路径上即可。
正解能 \(O(1)\) 合并, 然而这个解法需要\(O(logN)\)
所以总复杂度为 \(O(Nlog^2N)\)
Code #include #include #include #include #include #define up(a, b) (a = a > b ? a : b) #define down(a, b) (a = a > b ? b : a) #define cmax(a, b) (a > b ? a : b) #define cmin(a, b) (a > b ? b : a) #define Abs(a) ((a) > 0 ? (a) : -(a)) #define rd read() #define db double #define LL long long using namespace std; typedef pair P; inline char nc(){ static char buf[1<<14],*p1=buf,*p2=buf; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++; } inline int read(){ char c=nc();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();} while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();} return x*f; } const int N = 2e5 + 5; int n, m, a[N], b[N], f[N][20], dep[N]; int timer, tin[N], tout[N]; vector to[N]; void dfs(int u) { tin[u] = ++timer; // dfs序 for (int i = 0, up = to[u].size(); i int nt = to[u][i]; if (nt == f[u][0]) continue; dep[nt] = dep[u] + 1; dfs(nt); } tout[u] = timer; } inline bool isanc(int u, int v) { // 判断u是否是v的祖先 return tin[u] <= tin[v] && tout[u] >= tout[v]; } int getlca(int u, int v) { if (isanc(u, v)) return u; for (int i = 19; ~i; --i) if (f[u][i] && (!isanc(f[u][i], v))) u = f[u][i]; return f[u][0]; } inline bool isondownpath(int u, P v) { //判断u是否是 竖直路径v() 上的点 return isanc(v.first, u) && isanc(u, v.second); } inline bool isonpath(int u, P v) { //判断u是否是 路径v()上的点 int lca = getlca(v.first, v.second); return isondownpath(u, P(lca, v.second)) || isondownpath(u, P(lca, v.first)); } P merge(P u, P v) { //合并两条路径 if (u.first == -1 || v.first == -1) return P(-1, -1); int g[4] = {u.first, u.second, v.first, v.second}; for (int i = 0; i <4; ++i) { for (int j = i + 1; j <4; ++j) { bool flag = true; for (int k = 0; k <4; ++k) { if (k != i && k != j && !isonpath(g[k], P(g[i], g[j]))) flag = false; } if (flag) return P(g[i], g[j]); } } return P(-1, -1); } namespace SegT { #define mid ((l + r) >> 1) #define lson u <<1 #define rson u <<1 | 1 P t[N <<2]; void build(int l, int r, int u) { if (l == r) { t[u].first = t[u].secOnd= b[l]; return; } build(l, mid, lson); build(mid + 1, r, rson); t[u] = merge(t[lson], t[rson]); } void update(int c, int l, int r, int u) { if (l == r) { t[u].first = t[u].secOnd= b[l]; return; } if (c <= mid) update(c, l, mid, lson); else update(c, mid + 1, r, rson); t[u] = merge(t[lson], t[rson]); } int query(int l, int r, int u, P tmp) { if (l == r) { if (tmp.first == -1) return t[u].first != -1; P g = merge(tmp, t[u]); return g.first != -1; } P g = tmp.first == -1 ? t[lson] : merge(tmp, t[lson]); if (g.first == -1) return query(l, mid, lson, tmp); else return mid - l + 1 + query(mid + 1, r, rson, g); } }using namespace SegT; int main() { n = rd; for (int i = 1; i <= n; ++i) a[i] = rd + 1, b[a[i]] = i; for (int i = 2; i <= n; ++i) { int u = rd; f[i][0] = u; to[u].push_back(i); to[i].push_back(u); } dep[1] = 1; dfs(1); for (int i = 1; i <20; ++i) for (int j = 1; j <= n; ++j) f[j][i] = f[f[j][i - 1]][i - 1]; ; build(1, n, 1); m = rd; for (; m; --m) { int typ = rd; if (typ == 1) { int u = rd, v = rd; swap(a[u], a[v]); swap(b[a[u]], b[a[v]]); update(a[u], 1, n, 1); update(a[v], 1, n, 1); } else printf("%d\n", query(1, n, 1, P(-1, -1))); } }
Max Mex
推荐阅读
本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ...
[详细]
蜡笔小新 2024-12-28 08:44:35
在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ...
[详细]
蜡笔小新 2024-12-27 15:26:10
本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ...
[详细]
蜡笔小新 2024-12-27 11:26:39
本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ...
[详细]
蜡笔小新 2024-12-26 19:26:18
本文介绍如何在 Android 中通过代码模拟用户的点击和滑动操作,包括参数说明、事件生成及处理逻辑。详细解析了视图(View)对象、坐标偏移量以及不同类型的滑动方式。 ...
[详细]
蜡笔小新 2024-12-28 12:12:22
本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ...
[详细]
蜡笔小新 2024-12-28 11:30:01
Java 中 Writer flush()方法,示例 ...
[详细]
蜡笔小新 2024-12-28 06:41:52
主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ...
[详细]
蜡笔小新 2024-12-27 18:18:10
题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ...
[详细]
蜡笔小新 2024-12-27 18:14:31
本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ...
[详细]
蜡笔小新 2024-12-27 16:07:12
前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ...
[详细]
蜡笔小新 2024-12-27 15:19:01
在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ...
[详细]
蜡笔小新 2024-12-27 12:39:06
学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ...
[详细]
蜡笔小新 2024-12-26 20:04:36
This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ...
[详细]
蜡笔小新 2024-12-26 19:13:45
题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!----- ...
[详细]
蜡笔小新 2024-12-26 15:55:56
吻过彩虹的脸_378
这个家伙很懒,什么也没留下!