zoukankan      html  css  js  c++  java
  • 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
    ", 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 }
  • 相关阅读:
    [工控安全][原创]施耐德某PLC模块用户密码相关漏洞
    [工控安全][原创]施耐德某PLC模块敏感信息泄露漏洞
    [工控安全][原创]西门子PLC固件逆向之定位s7comm协议的一个切入口
    [安全工具][原创]保存IDA Pro中生成的函数调用关系(图)
    [工控安全][原创]西门子PLC固件逆向之socket API(总览)
    [工控安全][原创]面向开环控制的震网病毒恶意载荷探究
    [工控安全][翻译]Rogue7:西门子s7comm-plus协议全解析
    [工控/IOT安全][笔记]ARM设备固件装载基址定位的研究
    Tor源码阅读与改造(一)
    Java WebDriver 使用经验
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10101996.html
Copyright © 2011-2022 走看看