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的更多相关文章

  1. CF 526F Max Mex(倍增求LCA+线段树路径合并)

    Max Mex 题目地址:https://codeforces.com/contest/1084/problem/F 然后合并时注意分情况讨论: 参考代码: #include<bits/stdc ...

  2. Codeforces 1083C Max Mex

    Description 一棵\(N\)个节点的树, 每个节点上都有 互不相同的 \([0, ~N-1]\) 的数. 定义一条路径上的数的集合为 \(S\), 求一条路径使得 \(Mex(S)\) 最大 ...

  3. Max Mex

    Max Mex 无法直接处理 可以二分答案! [0,mid]是否在同一个链上? 可以不修改地做了 修改? 能不能信息合并?可以! 记录包含[l,r]的最短链的两端 可以[0,k][k+1,mid]合并 ...

  4. CF1083C Max Mex 线段树

    题面 CF1083C Max Mex 题解 首先我们考虑,如果一个数x是某条路径上的mex,那么这个数要满足什么条件? 1 ~ x - 1的数都必须出现过. x必须没出现过. 现在我们要最大化x,那么 ...

  5. CodeForces 1084 F Max Mex

    Max Mex 题意:问在树上的所有路中mex值最大是多少. 题解: 用线段树维护值. 区间[L,R]意味着 区间[L,R]的数可不可以合并. 重点就是合并的问题了. 首先合法的区间只有3种: 1. ...

  6. 【Codeforces 1083C】Max Mex(线段树 & LCA)

    Description 给定一颗 \(n\) 个顶点的树,顶点 \(i\) 有点权 \(p_i\).其中 \(p_1,p_2,\cdots, p_n\) 为一个 \(0\sim (n-1)\) 的一个 ...

  7. 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 题意: 在一棵树内找一条路径,使得从起点 ...

  8. [CF1083C]Max Mex

    题目大意:有一棵$n(n\leqslant2\times10^5)$个点的树,每个点有点权,所有的点权构成了$0\sim n-1$的排列.$q(q\leqslant2\times10^5)$次操作,操 ...

  9. 【线段树】【CF1083C】 Max Mex

    Description 给定一棵有 \(n\) 个点的树,每个节点有点权.所有的点权构成了一个 \(0~\sim~n - 1\) 的排列.有 \(q\) 次操作,每次操作 \(1\) 为交换两个点的点 ...

随机推荐

  1. 马克飞象markdown用法

    目录 markdown用法 ### 根据标题生成目录 `` 快捷键 ctrl+k 代码区域 ctrl+2 二级标题 ctrl+b/i 粗体/斜体 ctrl+l 插入链接 ctrl+g 插入图片 ctr ...

  2. 【vue】饿了么项目-header组件开发

    1.数据传递的理解 在App.vue中用到了header组件,首先注册组件 components: { 'v-header': header } 然后才能引用 <v-header :seller ...

  3. 3、Android-全局大喇叭-广播机制

    所谓的官博机制可以理解成为1对多的概念 即一个喇叭所有的人都能听到(统一范围内) 为了便于及逆行系统级别的消息通知 Android引入了一套广播机制 而且更容易进行实现. 3.1.广播机制的简介 再A ...

  4. leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence

    Longest Increasing Subsequence 最长递增子序列 子序列不是数组中连续的数. dp表达的意思是以i结尾的最长子序列,而不是前i个数字的最长子序列. 初始化是dp所有的都为1 ...

  5. keras写模型时遇到的典型问题,也是最基础的类与对象问题

    自己定义了一个卷积类,现在需要把卷积加入model中,我的操作是这样的: model.add(Convolution1dLayer) 这样就会报错: 正确的写法是: model.add(Convolu ...

  6. DPI在SDN中的部署方式

    目录 在sdn中的部署分类 将DPI部署到基础设施层 将DPI部署到控制层 将DPI部署到应用层 个人总结 参考文献 在sdn中的部署分类 DPI 可以分别部署到SDN的基础设施层.控制层和应用层. ...

  7. 如何弹出WiFi提示列表。

    如果你的程序中用到了WiFi,想在没有有效WiFi的时候出现如图所示的提示该怎么做? 其实很简单, 只需要在Info.plist中添加如下Key/Value UIRequiresPersistentW ...

  8. MySQL->导出/导入资料[20180521]

    MySQL 导出     INTO OUTFILE将资料导出至文件中     mysqldump工具导出资料和数据结构,并且可以针对数据库.数据表.索引的结构.   INTO OUTFILE测试   ...

  9. bootstrap世界探索1——山川河流(文字排版)

    世界到底是什么?其实世界很简单,正所谓一花一世界,一树一菩提,世界就在我们身边.造物神是伟大的,在我看来无论是HTML,css,js都可以看作是一个世界,但是他们是构成宏观世界不可或缺的,正如IU框架 ...

  10. JavaScript入门学习(1)

    <html> <script type ="text/javascript"> var i,j; for (i=1;i<10;i++){ for (j ...