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

  1. $1\;x\;y:$交换$x$和$y$的点权
  2. $2:$询问$\max\limits_{x,y\in V}\{mex(x\to y)\}$

题解:这个明显具有可二分性(然后我考场上写了一个虚树判链的,复杂度爆炸+没用)。翻看题解知道这道题可以用线段树来维护区间点是否在一条链上,在区间合并的时候枚举一下在两个区间的四个端点中是哪两个端点为大区间的端点,用$LCA$以及$dfn$序判断一下即可。

在最开始判一下树的形态是一条链的情况

卡点:

C++ Code:

#include <algorithm>
#include <cctype>
#include <cstdio>
namespace __IO {
int ch;
inline int read() {
static int x;
while (isspace(ch = getchar())) ; x = ch & 15;
while (isdigit(ch = getchar())) x = x * 10 + (ch & 15);
return x;
}
}
using __IO::read; #define maxn 200010
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn];
inline void addedge(int a, int b) {
e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
} int fa[maxn], sz[maxn], dep[maxn];
int top[maxn], dfn[maxn], idx;
int find(int x) { return x == top[x] ? x : (top[x] = find(top[x])); }
void dfs(int u) {
int son = 0;
dfn[u] = ++idx, sz[u] = 1;
for (int i = head[u], v; i; i = e[i].nxt) {
v = e[i].to;
dep[v] = dep[u] + 1;
dfs(v), sz[u] += sz[v];
if (sz[v] > sz[son]) son = v;
}
if (son) top[son] = u;
}
inline int LCA(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]]) x = fa[top[x]];
else y = fa[top[y]];
}
return dep[x] < dep[y] ? x : y;
} int n, m, w[maxn], ret[maxn]; inline bool in_sub(int x, int y) {
return (dfn[x] >= dfn[y]) && (dfn[x] < dfn[y] + sz[y]);
}
inline bool in_line(int x, int y, int z) {
static int lca; lca = LCA(x, y);
return in_sub(z, lca) && (in_sub(x, z) || in_sub(y, z));
}
inline bool in_line(int x, int y, int l, int r) {
return in_line(x, y, l) && in_line(x, y, r);
} struct node {
bool line;
int l, r;
inline node() { }
inline node(int __l) : line(true), l(__l), r(__l) { }
inline node(int __l, int __r) : line(true), l(__l), r(__r) { }
inline node(bool __line, int __l, int __r) : line(__line), l(__l), r(__r) { }
static inline node NS() { return node(0, -1, -1); }
inline node operator + (const node &rhs) const {
if (!l || !r) return rhs;
if (!line || !rhs.line) return NS();
const int x = rhs.l, y = rhs.r;
if (in_line(l, r, x, y)) return node(l, r);
if (in_line(l, x, r, y)) return node(l, x);
if (in_line(l, y, x, r)) return node(l, y);
if (in_line(r, x, l, y)) return node(r, x);
if (in_line(r, y, l, x)) return node(r, y);
if (in_line(x, y, l, r)) return node(x, y);
return NS();
}
} I(0, 0, 0); namespace SgT {
node V[maxn << 2];
void build(const int rt, const int l, const int r) {
if (l == r) {
V[rt] = node(ret[l]);
return ;
}
const int mid = l + r >> 1;
build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
V[rt] = V[rt << 1] + V[rt << 1 | 1];
} int pos;
void __modify(const int rt, const int l, const int r) {
if (l == r) {
V[rt] = node(ret[l]);
return ;
}
const int mid = l + r >> 1;
if (pos <= mid) __modify(rt << 1, l, mid);
else __modify(rt << 1 | 1, mid + 1, r);
V[rt] = V[rt << 1] + V[rt << 1 | 1];
}
void modify(const int __pos) {
pos = __pos;
__modify(1, 0, n - 1);
} node now;
int res;
void __query(int rt, int l, int r) {
if (l == r) {
res = l;
return ;
}
node tmp = now + V[rt << 1];
const int mid = l + r >> 1;
if (tmp.line) {
now = tmp;
__query(rt << 1 | 1, mid + 1, r);
} else __query(rt << 1, l, mid);
}
int query() {
now = I, res = 1;
__query(1, 0, n - 1);
return res;
}
} int ind[maxn];
bool is_line = true;
int main() {
n = read();
for (int i = 1; i <= n; ++i) {
w[i] = read();
ret[w[i]] = top[i] = i;
}
for (int i = 2; i <= n; ++i) {
fa[i] = read();
addedge(fa[i], i);
++ind[fa[i]], ++ind[i];
if (ind[fa[i]] > 2 || ind[i] > 2) is_line = false;
}
dfs(1);
for (int i = 1; i <= n; ++i) find(i);
SgT::build(1, 0, n - 1); m = read();
while (m --> 0) {
static int op, x, y;
op = read();
if (op == 1) {
x = read(), y = read();
std::swap(ret[w[x]], ret[w[y]]), std::swap(w[x], w[y]);
if (!is_line) SgT::modify(w[x]), SgT::modify(w[y]);
} else printf("%d\n", is_line ? n : SgT::query());
}
return 0;
}

  

[CF1083C]Max Mex的更多相关文章

  1. CF1083C Max Mex 线段树

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

  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. CF 1083 C. Max Mex

    C. Max Mex https://codeforces.com/contest/1083/problem/C 题意: 一棵$n$个点的树,每个点上有一个数(每个点的上的数互不相同,而且构成一个0~ ...

  5. CodeForces 1084 F Max Mex

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

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

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

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

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

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

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

  9. Codeforces 1083C Max Mex [线段树]

    洛谷 Codeforces 思路 很容易发现答案满足单调性,可以二分答案. 接下来询问就转换成判断前缀点集是否能组成一条链. 我最初的想法:找到点集的直径,判断直径是否覆盖了所有点,需要用到树套树,复 ...

随机推荐

  1. JAVA面试中问及HIBERNATE与 MYBATIS的对比

    第一方面:开发速度的对比 就开发速度而言,Hibernate的真正掌握要比Mybatis来得难些.Mybatis框架相对简单很容易上手,但也相对简陋些.个人觉得要用好Mybatis还是首先要先理解好H ...

  2. MySQL高级-全局查询日志

    注意:全局查询日志不要在生成环境中启用 一.配置启用 二.编码启用

  3. 「日常训练」Balancing Act(POJ-1655)

    题意与分析 树的重心板子题. 值得考虑的是,重心究竟有哪些优秀的性质? 这里是一些网上能看到的性质: (判定性质)找到一个点,其所有的子树中最大的子树节点数最少(子树可以"倒着看" ...

  4. MySQL☞关联查询

    关联查询:所需要的数据来源于多张表,通过表的连接查询(关联查询)来查询多张表中的数据 格式: select 别名1 . */列名 , 别名2 . */列名 from 表名1  别名1 , 表名2  别 ...

  5. 如何往eclipse中导入maven项目

    现在公司中大部分项目可能都是使用maven来构建,假如现在摆在你面前有一个maven的项目,如果你要学习它,如何将它导入到像eclipse这样的集成开发工具中呢,以项目public_class_1为例 ...

  6. Codeforces Round #495 (Div. 2) Sonya and Matrix

    正常没有正方形的限制下,值为i的点个数4i 那么从0开始遍历,第一个不为4i的值就是min(x, y) 由于对称性我们姑且令x为这个值 我们先列举n*m=t的各种情况 对于一对n, m.我们已经知道n ...

  7. 【setUp-tearDown】线程组开始,结束各执行一次

    使用setUp线程组的方式  ——> 开始 使用tearDown线程组 的方式 ——>结束

  8. 【20180807模拟测试】T2 box

    [问题描述] 有个桌子长 R 宽 C,被分为 R*C 个小方格.其中,一些方格上有箱子,一些方格上有按 钮,一些方格上有障碍物,一些方格上是空地.现在有个任务,需要把所有箱子推到这些按 钮上面.箱子有 ...

  9. ServiceStack.Ormlit 使用Insert的时候自增列不会被赋值

    Insert签名是这样的,将第2个参数设置为true就会返回刚插入的自增列ID了,然后可以手工赋值到对象上面去 public static long Insert<T>(this IDbC ...

  10. CentOS6 安装VNCserver

    1.下载vncserver yum install tigervnc tigervnc-server -y 2.配置 vncserver vi /etc/sysconfig/vncserver 在文件 ...