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 }

 

posted @ 2018-12-11 14:28  MJT12044  阅读(552)  评论(1编辑  收藏  举报