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. Python version 3.6 required, which was not found in the registry错误解决

    问题: 安装pywin32出现Python version 3.6 required, which was not found in the registry错误解决 解决: 建立一个文件 regis ...

  2. A blog about Core Animation and other iOS graphics framework

    A blog about Core Animation and other iOS graphics frameworks. https://www.calayer.com/

  3. GPU性能:光栅化、图层混合、离屏渲染

    So, shouldRasterize will not affect the green/red you see using Instruments. In order to have everyt ...

  4. TTransport 概述

    TTransport TTransport主要作用是定义了IO读写操作以及本地缓存的操作,下面来看TIOStreamTransport是如何实现的. public abstract class TTr ...

  5. Web项目打成war包部署Tomcat时运行startup.bat直接闪退部署失败解决方案

    即上篇通过将web项目打成war包部署到Tomcat服务器,解决mysql问题后,又出现了新问题,真是一波三折,所以将解决过程分享给大家,希望能帮助到小伙伴们~ 将打好的war包拷贝到Tomcat的w ...

  6. TensorFlow学习('utf-8' codec can't decode byte 0xff in position 0: invalid start byte)

    使用语句: image_raw_data = tf.gfile.GFile("./picture.jpg", "r").read() 读取图像时报错如下: Un ...

  7. [19/05/02-星期四] GOF23_行为型模式(状态模式、观察者模式、备忘录模式)

    一.状态模式 [状态接口] /*** * 房间"状态"接口 */ package cn.sxt.state; public interface State { void handl ...

  8. 由于开发需求需要在附件查看页面添加水印,于是网上看到一位大牛写了一个js加水印的方法觉得很实用,也很方便,记录一下,哈哈

    大牛的博客链接:https://www.cnblogs.com/daixinyu/p/6715398.html 提供给大家学习 我优化了几点 1,我把水印的样式单独提出来,这样会提高渲染水印的性能 2 ...

  9. MFC各个控件之间运用SendMessage()传送CString和char[]字符串,以及int类型数据

    LRESULT SendMessage( HWND hWnd, // handle to destination window UINT Msg, // message WPARAM wParam, ...

  10. jmeter接口测试2-断言

    接上篇 要想更好的查看接口测试结果,可以添加断言 举一个最简单的响应断言的例子 前提环境:根据接口文档可知,待测试接口返回值1,-1,-2,-3 (1)添加断言 (2)设置断言内容,看响应的内容是否含 ...