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. 洛谷 P4783 【模板】矩阵求逆

    题目分析 模板题. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e ...

  2. 【[TJOI2017]异或和】

    这道题挺神仙的,毕竟这个异或是需要进位的 看到区间和我们很自然的就想到了前缀和 于是处理一下前缀和答案就变成了这个样子 \[⊕\sum_{i=1}^n\sum_{j=1}^{i}pre_i-pre_{ ...

  3. P2059 [JLOI2013]卡牌游戏

    题目描述 N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把 ...

  4. ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters

    转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9281366.html  ValueError: All strings must be XML compati ...

  5. 通讯协议(二)HTTPS协议

    摘要:本文尝试一步步还原HTTPS的设计过程,以理解为什么HTTPS最终会是这副模样.但是这并不代表HTTPS的真实设计过程.在阅读本文时,你可以尝试放下已有的对HTTPS的理解,这样更利于“还原”过 ...

  6. disconf实践(三)基于XML的分布式配置文件管理,自动reload

    上一篇介绍了基于xml的非自动reload的分布式配置文件管理,这一篇介绍自动reload的方式(基于disconf实践二). 1. 修改RedisConfig.java package org.sp ...

  7. JavaIO流(输入输出操作)

    Java中执行输出和输入操作,需要通过IO流.例如最常见的System.out.println()就是一个输出流.IO流的类比较多,但核心体系就是由File. InputStream .OutputS ...

  8. Python 基础 Dict 和 Set 类型

    python 什么是dict 例如: d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 } 我们把名称称为key,对应的成绩称为value,dic就是通过key 来查找 ...

  9. Ubuntu下配置jdk和tomcat

    一.配置jdk 更新系统 apt-get update 添加ppa add-apt-repository ppa:webupd8team/java 开始安装 apt-get install oracl ...

  10. RedirectAttributes 之 IE8请求跳转失败

    1.时间真快,一晃又快冬天了,下了第一场雪.雪花漫漫,堵车悠悠. 2.这次遇到这样一个问题,就是RedirectAttributes传递数据参数,如果参数数据过大,在IE8浏览器时候会跳转不过去.其实 ...