CF 1083 C. Max Mex
C. Max Mex
https://codeforces.com/contest/1083/problem/C
题意:
一棵$n$个点的树,每个点上有一个数(每个点的上的数互不相同,而且构成一个0~n-1的排列),要求找到一条路径,使得路径的$mex$最大。
分析:
问题转化为,查询一个a,0~a-1是否可以都存在于一条路径上。类似线段树维护连通性,这里线段树的每个点表示所对应的区间[l,r]是否可以存在于一条路径上。合并的时候用lca和dfs序的位置判断。然后就是线段树上二分了。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define Root 0, n - 1, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
const int Log = ; struct Edge{
int to, nxt;
Edge() {}
Edge(int a,int b) { to = a, nxt = b; }
}e[N];
int head[N], a[N], per[N], In[N], Ou[N], deth[N], f[N][Log + ], En, Index;
struct Node{
int x, y;
Node() {}
Node(int _x,int _y) { x = _x, y = _y; }
}T[N << ];
bool operator < (const Node &A,const Node &B) {
return A.x == B.x ? A.y < B.y : A.x < B.x;
}
int Jump(int x,int ly) {
for (int i = Log; i >= ; --i)
if (deth[f[x][i]] >= ly) x = f[x][i]; // 这里要求deth[1]=1
return x;
}
int LCA(int u,int v) {
if (deth[u] < deth[v]) swap(u, v);
int d = deth[u] - deth[v];
for (int i = Log; i >= ; --i)
if ((d >> i) & ) u = f[u][i];
if (u == v) return u;
for (int i = Log; i >= ; --i)
if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
return f[u][];
}
bool onpath(int x,int y,int z) {
int anc = LCA(x, y);
if (deth[anc] > deth[z]) return ;
return Jump(x, deth[z]) == z || Jump(y, deth[z]) == z;
}
Node operator + (const Node &A,const Node &B) {
int a = A.x, b = A.y, c = B.x, d = B.y;
if (a == - || b == - || c == - || d == -) return Node(-, -);
int x = min(Node(Ou[a], a), min(Node(Ou[b], b), min(Node(Ou[c], c), Node(Ou[d], d)))).y; //dfs序上较小的路位置
int y = max(Node(In[a], a), max(Node(In[b], b), max(Node(In[c], c), Node(In[d], d)))).y; //dfs序上较大的路位置
if (x == y) { // 在同一条链上的情况
int z = min(Node(deth[a], a), min(Node(deth[b], b), min(Node(deth[c], c), Node(deth[d], d)))).y;
return Node(z, x);
}
else if (onpath(x, y, a) && onpath(x, y, b) && onpath(x, y, c) && onpath(x, y, d)) return Node(x, y);
else return Node(-, -);
}
inline void add_edge(int u,int v) {
++En; e[En] = Edge(v, head[u]); head[u] = En;
}
void dfs(int u) {
In[u] = ++Index;
for (int i = head[u]; i; i = e[i].nxt) deth[e[i].to] = deth[u] + , dfs(e[i].to);
Ou[u] = ++Index;
}
void build(int l,int r,int rt) {
if (l == r) {
T[rt].x = T[rt].y = per[l]; return ;
}
int mid = (l + r) >> ;
build(lson); build(rson);
T[rt] = T[rt << ] + T[rt << | ];
}
void update(int l,int r,int rt,int p,int v) {
if (l == r) {
T[rt].x = T[rt].y = v; return ;
}
int mid = (l + r) >> ;
if (p <= mid) update(lson, p, v);
if (p > mid) update(rson, p, v);
T[rt] = T[rt << ] + T[rt << | ];
}
int query(int l,int r,int rt,Node now) {
if (l == r) {
return (now + T[rt]).x == - ? l - : l;
}
int mid = (l + r) >> ;
Node tmp = now + T[rt << ];
if (tmp.x == -) return query(lson, now);
else return query(rson, tmp);
}
int main() {
int n = read();
for (int i = ; i <= n; ++i) a[i] = read(), per[a[i]] = i; // a[i]第i个节点的数,per[i]数字为i的在树的那个节点上
for (int i = ; i <= n; ++i) {
int fa = read();
add_edge(fa, i);
f[i][] = fa;
}
for (int j = ; j <= Log; ++j)
for (int i = ; i <= n; ++i)
f[i][j] = f[f[i][j - ]][j - ];
deth[] = ; dfs();
build(Root);
int Q = read();
while (Q--) {
int opt = read();
if (opt == ) {
printf("%d\n", query(Root, Node(per[], per[])) + );
continue;
}
int x = read(), y = read();
swap(per[a[x]], per[a[y]]);
update(Root, a[x], per[a[x]]);
update(Root, a[y], per[a[y]]);
swap(a[x], a[y]);
}
return ;
}
CF 1083 C. Max Mex的更多相关文章
- CF 526F Max Mex(倍增求LCA+线段树路径合并)
Max Mex 题目地址:https://codeforces.com/contest/1084/problem/F 然后合并时注意分情况讨论: 参考代码: #include<bits/stdc ...
- Codeforces 1083C Max Mex
Description 一棵\(N\)个节点的树, 每个节点上都有 互不相同的 \([0, ~N-1]\) 的数. 定义一条路径上的数的集合为 \(S\), 求一条路径使得 \(Mex(S)\) 最大 ...
- Max Mex
Max Mex 无法直接处理 可以二分答案! [0,mid]是否在同一个链上? 可以不修改地做了 修改? 能不能信息合并?可以! 记录包含[l,r]的最短链的两端 可以[0,k][k+1,mid]合并 ...
- CF1083C Max Mex 线段树
题面 CF1083C Max Mex 题解 首先我们考虑,如果一个数x是某条路径上的mex,那么这个数要满足什么条件? 1 ~ x - 1的数都必须出现过. x必须没出现过. 现在我们要最大化x,那么 ...
- CodeForces 1084 F Max Mex
Max Mex 题意:问在树上的所有路中mex值最大是多少. 题解: 用线段树维护值. 区间[L,R]意味着 区间[L,R]的数可不可以合并. 重点就是合并的问题了. 首先合法的区间只有3种: 1. ...
- 【Codeforces 1083C】Max Mex(线段树 & LCA)
Description 给定一颗 \(n\) 个顶点的树,顶点 \(i\) 有点权 \(p_i\).其中 \(p_1,p_2,\cdots, p_n\) 为一个 \(0\sim (n-1)\) 的一个 ...
- CF 1083 A. The Fair Nut and the Best Path
A. The Fair Nut and the Best Path https://codeforces.com/contest/1083/problem/A 题意: 在一棵树内找一条路径,使得从起点 ...
- [CF1083C]Max Mex
题目大意:有一棵$n(n\leqslant2\times10^5)$个点的树,每个点有点权,所有的点权构成了$0\sim n-1$的排列.$q(q\leqslant2\times10^5)$次操作,操 ...
- 【线段树】【CF1083C】 Max Mex
Description 给定一棵有 \(n\) 个点的树,每个节点有点权.所有的点权构成了一个 \(0~\sim~n - 1\) 的排列.有 \(q\) 次操作,每次操作 \(1\) 为交换两个点的点 ...
随机推荐
- 1221. [HNOI2001]软件开发【费用流】
Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...
- C# winform 数据库操作知识点总结(干货)
1.数据库连接及操作 在说数据库操作之前,先说一下数据库连接操作字符串的获取 首先,点击服务器资源管理器,接下来选中数据连接右键点击添加连接,填入你要连接的服务器名称,点击单选框使用SQL Serve ...
- Hadoop学习之路(二十六)MapReduce的API使用(三)
影评案例 数据及需求 数据格式 movies.dat 3884条数据 1::Toy Story (1995)::Animation|Children's|Comedy 2::Jumanji (1995 ...
- Python 模块化 from .. import 语句资源搜索顺序 (三)
接着上一篇文章最后的import子句资源搜索顺序,我们来写几个例子了解下. 例一. #test1.py x = 123 #test.py import test1 print(dir()) print ...
- selenium + python自动化测试unittest框架学习(七)随机生成姓名
在自动化测试过程中经常要测试到添加用户的操作,每次都要输入中文,原本是找了十几个中文写成了列表,然后从列表中随机取出填入用户名文本框中,随着测试的增加,发现同名的人搜索出来一大堆,最后在网上找了个随机 ...
- YourUninstaller注册码(可用)
Name:Giveawayoftheday Registration code: 000017-2PNBK2-J59U6F-317E09-R5TGJQ-6B1WNA-AZCYNJ-GVP86A-7VP ...
- 关于PCA的一些学习汇总
主成分分析PCA算法:为什么去均值以后的高维矩阵乘以其协方差矩阵的特征向量矩阵就是“投影”? https://www.zhihu.com/question/30094611 还有一些疑问:1.这个散步 ...
- 字符型设备驱动程序-first-printf以及点亮LED灯(一)
学习使用 Linux 的 字符型设备驱动 来 进行 . 学习地址:http://edu.51cto.com/lesson/id-25710.html 第一步: 首先写 三个函数 ,2017年5月17 ...
- SQLIO 磁盘測试工具參考
SQLIO 下载地址:id=20163">SQLIO Disk Subsystem Benchmark Tool 默认文件夹:C:\Program Files\SQLIO 以命令行执行 ...
- 三、Shiro授权开发
Shiro 支持三种方式的授权: I. 编程式:通过写if/else 授权代码块完成: Subject subject =SecurityUtils.getSubject(); if(subject. ...