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序的位置判断。然后就是线段树上二分了。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 #define Root 0, n - 1, 1 12 #define lson l, mid, rt << 1 13 #define rson mid + 1, r, rt << 1 | 1 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 200005; 23 const int Log = 22; 24 25 struct Edge{ 26 int to, nxt; 27 Edge() {} 28 Edge(int a,int b) { to = a, nxt = b; } 29 }e[N]; 30 int head[N], a[N], per[N], In[N], Ou[N], deth[N], f[N][Log + 1], En, Index; 31 struct Node{ 32 int x, y; 33 Node() {} 34 Node(int _x,int _y) { x = _x, y = _y; } 35 }T[N << 2]; 36 bool operator < (const Node &A,const Node &B) { 37 return A.x == B.x ? A.y < B.y : A.x < B.x; 38 } 39 int Jump(int x,int ly) { 40 for (int i = Log; i >= 0; --i) 41 if (deth[f[x][i]] >= ly) x = f[x][i]; // 这里要求deth[1]=1 42 return x; 43 } 44 int LCA(int u,int v) { 45 if (deth[u] < deth[v]) swap(u, v); 46 int d = deth[u] - deth[v]; 47 for (int i = Log; i >= 0; --i) 48 if ((d >> i) & 1) u = f[u][i]; 49 if (u == v) return u; 50 for (int i = Log; i >= 0; --i) 51 if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i]; 52 return f[u][0]; 53 } 54 bool onpath(int x,int y,int z) { 55 int anc = LCA(x, y); 56 if (deth[anc] > deth[z]) return 0; 57 return Jump(x, deth[z]) == z || Jump(y, deth[z]) == z; 58 } 59 Node operator + (const Node &A,const Node &B) { 60 int a = A.x, b = A.y, c = B.x, d = B.y; 61 if (a == -1 || b == -1 || c == -1 || d == -1) return Node(-1, -1); 62 int x = min(Node(Ou[a], a), min(Node(Ou[b], b), min(Node(Ou[c], c), Node(Ou[d], d)))).y; //dfs序上较小的路位置 63 int y = max(Node(In[a], a), max(Node(In[b], b), max(Node(In[c], c), Node(In[d], d)))).y; //dfs序上较大的路位置 64 if (x == y) { // 在同一条链上的情况 65 int z = min(Node(deth[a], a), min(Node(deth[b], b), min(Node(deth[c], c), Node(deth[d], d)))).y; 66 return Node(z, x); 67 } 68 else if (onpath(x, y, a) && onpath(x, y, b) && onpath(x, y, c) && onpath(x, y, d)) return Node(x, y); 69 else return Node(-1, -1); 70 } 71 inline void add_edge(int u,int v) { 72 ++En; e[En] = Edge(v, head[u]); head[u] = En; 73 } 74 void dfs(int u) { 75 In[u] = ++Index; 76 for (int i = head[u]; i; i = e[i].nxt) deth[e[i].to] = deth[u] + 1, dfs(e[i].to); 77 Ou[u] = ++Index; 78 } 79 void build(int l,int r,int rt) { 80 if (l == r) { 81 T[rt].x = T[rt].y = per[l]; return ; 82 } 83 int mid = (l + r) >> 1; 84 build(lson); build(rson); 85 T[rt] = T[rt << 1] + T[rt << 1 | 1]; 86 } 87 void update(int l,int r,int rt,int p,int v) { 88 if (l == r) { 89 T[rt].x = T[rt].y = v; return ; 90 } 91 int mid = (l + r) >> 1; 92 if (p <= mid) update(lson, p, v); 93 if (p > mid) update(rson, p, v); 94 T[rt] = T[rt << 1] + T[rt << 1 | 1]; 95 } 96 int query(int l,int r,int rt,Node now) { 97 if (l == r) { 98 return (now + T[rt]).x == -1 ? l - 1 : l; 99 } 100 int mid = (l + r) >> 1; 101 Node tmp = now + T[rt << 1]; 102 if (tmp.x == -1) return query(lson, now); 103 else return query(rson, tmp); 104 } 105 int main() { 106 int n = read(); 107 for (int i = 1; i <= n; ++i) a[i] = read(), per[a[i]] = i; // a[i]第i个节点的数,per[i]数字为i的在树的那个节点上 108 for (int i = 2; i <= n; ++i) { 109 int fa = read(); 110 add_edge(fa, i); 111 f[i][0] = fa; 112 } 113 for (int j = 1; j <= Log; ++j) 114 for (int i = 1; i <= n; ++i) 115 f[i][j] = f[f[i][j - 1]][j - 1]; 116 deth[1] = 1; dfs(1); 117 build(Root); 118 int Q = read(); 119 while (Q--) { 120 int opt = read(); 121 if (opt == 2) { 122 printf("%d\n", query(Root, Node(per[0], per[0])) + 1); 123 continue; 124 } 125 int x = read(), y = read(); 126 swap(per[a[x]], per[a[y]]); 127 update(Root, a[x], per[a[x]]); 128 update(Root, a[y], per[a[y]]); 129 swap(a[x], a[y]); 130 } 131 return 0; 132 }