CodeForces 1084 F Max Mex

Max Mex

题意:问在树上的所有路中mex值最大是多少。

题解:

用线段树维护值。

区间[L,R]意味着 区间[L,R]的数可不可以合并。

重点就是合并的问题了。

首先合法的区间只有3种:

1. 一个点。

2. 一条从上到下的线段  即 u->v  u = lca(u,v)。

3.一条从下到上到下的线段 u -> p -> v  p = lca(u,v) 

 1 和 1 可以直接合并, 合并之后可能成为 2 或者成为3。

 1 和 2 合并的时候 可能变成 2 或者 3。 注意的是 1 往上爬的时候可能出现在 2 的中间位置而不是端点位置。

 1 和 3 合并的之后 只会变成 3。并且 p 是不会变得,只有 u 和 v 会变。

 2 和 2 合并的时候 可能保持2 也可以变成3。

 2 和 3 合并的时候 只会保持3, 并且 p 一样不会边,只有u 和 v 会变。  1 3 合并的操作 和 2 3 合并的操作是一样的。

 3 和 3 合并的时候 只会保持3, 还是p不会边, u 和 v 会变。

所以 根据前面说的 我们要记录的是 type, u, v, p,ok。

询问的时候,我们先问出[1,x]哪一段是合法的,然后再在右边去询问能不能把右边的并到[1,x]上。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 2e5 + 100;
int anc[N][20];
int v[N], deep[N];
vector<int> vc[N];
void dfs(int o){
    for(int x : vc[o]){
        deep[x] = deep[o]+1;
        anc[x][0] = o;
        for(int i = 1; i < 19; ++i) anc[x][i] = anc[anc[x][i-1]][i-1];
        dfs(x);
    }
}
int lca(int u, int v){
    if(deep[u] > deep[v]) swap(u,v);
    int k = deep[v] - deep[u];
    for(int i = 19; i >= 0; --i){
        if((k>>i)&1) v = anc[v][i];
    }
    if(u == v) return u;
    for(int i = 19; i >= 0; --i){
        if(anc[u][i] != anc[v][i])
            u = anc[u][i], v = anc[v][i];
    }
    return anc[u][0];
}
int ok[N<<2], pre[N<<2], type[N<<2], low[N<<2][2];
void Merge(int rt, int ls, int rs){
    ok[rt] = 0;
    if(!ok[ls] || !ok[rs])  return;
    if(pre[ls] == low[ls][0] && pre[rs] == low[rs][0]){
        int fp = lca(pre[ls], pre[rs]);
        ok[rt] = 1; pre[rt] = fp;
        if(fp == pre[ls] || fp == pre[rs]){
            type[rt] = 1;
            if(fp == low[ls][0]) low[rt][0] = low[rs][0];
            else low[rt][0] = low[ls][0];
        }
        else {
            type[rt] = 2;
            low[rt][0] = pre[ls]; low[rt][1] = pre[rs];
        }
        return ;
    }
    if(pre[ls] == low[ls][0]) swap(ls, rs);
    if(type[ls] == 1 && type[rs] == 1 && pre[rs] == low[rs][0]){
        int fp = lca(pre[ls], pre[rs]);
        int sp = lca(low[ls][0], low[rs][0]);
        pre[rt] = fp;
        if(fp == sp){
            if(fp == pre[rs]) {
                ok[rt] = 1; type[rt] = 1;
                low[rt][0] = low[ls][0];
            }
            else {
                ok[rt] = 1; type[rt] = 2;
                low[rt][0] = low[ls][0]; low[rt][1] = low[rs][0];
            }
        }
        else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][0]||sp == low[rs][0])){
            ok[rt] = 1; type[rt] = 1;
            if(sp == low[ls][0]) low[rt][0] = low[rs][0];
            else low[rt][0] = low[ls][0];
        }
        return ;
    }
    if(type[ls] == 1 && type[rs] == 1){
        int fp = lca(pre[ls], pre[rs]);
        int sp = lca(low[ls][0], low[rs][0]);
        pre[rt] = fp;
        if(fp == sp){
            type[rt] = 2; ok[rt] = 1;
            low[rt][0] = low[ls][0]; low[rt][1] = low[rs][0];
        }
        else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][0]||sp == low[rs][0])){
            ok[rt] = 1; type[rt] =1 ;
            if(sp == low[ls][0]) low[rt][0] = low[rs][0];
            else low[rt][0] = low[ls][0];
        }
        else ok[rt] = 0;
        return ;
    }
    if(type[ls] + type[rs] == 3){
        if(type[ls] == 2) swap(ls, rs);
        int fp = lca(pre[ls], pre[rs]);
        if(fp != pre[rs]) ok[rt] = 0;
        else {
            type[rt] = 2; pre[rt] = fp;
            int sp = lca(low[ls][0], low[rs][0]);
            if(sp == low[ls][0]){
                low[rt][0] = low[rs][0]; low[rt][1] = low[rs][1];
                ok[rt] = 1;
                return ;
            }
            if(sp == low[rs][0]){
                low[rt][0] = low[ls][0];
                low[rt][1] = low[rs][1]; ok[rt] = 1;
                return ;
            }
            sp = lca(low[ls][0], low[rs][1]);
            if(sp == low[ls][0]){
                low[rt][0] = low[rs][0]; low[rt][1] = low[rs][1];
                ok[rt] = 1;
                return ;
            }
            if(sp == low[rs][1]){
                low[rt][0] = low[rs][0]; low[rt][1] = low[ls][0];
                ok[rt] = 1;
                return ;
            }
            return ;
        }
        return ;
    }
    if(type[ls] + type[rs] == 4){
        type[rt] = 2;
        if(pre[ls] == pre[rs]){
            pre[rt] = pre[ls];
            int sp1 = lca(low[ls][0], low[rs][0]), sp2 = lca(low[ls][1], low[rs][1]);
            if((sp1 == low[ls][0] || sp1 == low[rs][0]) && (sp2 == low[ls][1] || sp2 == low[rs][1])){
                ok[rt] = 1;
                if(sp1 == low[ls][0]) low[rt][0] = low[rs][0];
                else low[rt][0] = low[ls][0];
                if(sp2 == low[ls][1]) low[rt][1] = low[rs][1];
                else low[rt][1] = low[ls][1];
                return ;
            }
            sp1 = lca(low[ls][0], low[rs][1]), sp2 = lca(low[ls][1], low[rs][0]);
            if((sp1 == low[ls][0] || sp1 == low[rs][1]) && (sp2 == low[ls][1] || sp2 == low[rs][0])){
                ok[rt] = 1;
                if(sp1 == low[ls][0]) low[rt][0] = low[rs][1];
                else low[rt][0] = low[ls][0];
                if(sp2 == low[ls][1]) low[rt][1] = low[rs][0];
                else low[rt][1] = low[ls][1];
                return ;
            }
        }
    }
}
void Update(int L, int k, int l, int r, int rt){
    if(l == r){
        type[rt] = ok[rt] = 1;
        low[rt][0] = pre[rt] = k;
        return ;
    }
    int m = l+r >> 1;
    if(L <= m) Update(L, k, lson);
    else Update(L, k, rson);
    Merge(rt, rt<<1, rt<<1|1);
}
void Copy(int aim, int f){
    ok[aim] = ok[f]; pre[aim] = pre[f];
    low[aim][0] = low[f][0]; low[aim][1] = low[f][1];
    type[aim] = type[f];
}
int n, u;
int to = (200000<<2)+10, b = 0, ansr;
int Query(int l, int r, int rt){
    if(ok[rt]){
        if(b == 0) {
            b = to; ansr = r; Copy(b, rt);
            return 1;
        }
        Merge(to+1, to, rt);
        if(ok[to+1]){
            Copy(to, to+1); ansr = r;
            return 1;
        }
        if(l != r){
            int m = l+r >> 1;
            int k = Query(lson);
            if(k == 1) Query(rson);
        }
        return 0;
    }
    int m = l+r >> 1;
    int k = Query(lson);
    if(k == 1) Query(rson);
    return 0;
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &v[i]), v[i] += 1;
    for(int i = 2; i <= n; ++i){
        scanf("%d", &u);
        vc[u].pb(i);
    }
    dfs(1);
    for(int i = 1; i <= n; ++i)
        Update(v[i], i, 1, n, 1);
    int q, op, l, r;
    scanf("%d", &q);
    while(q--){
        scanf("%d", &op);
        if(op == 1){
            scanf("%d%d", &l, &r); swap(v[l], v[r]);
            Update(v[l], l, 1, n, 1); Update(v[r], r, 1, n, 1);
        }
        else {
            b = 0; Query(1,n,1);
            printf("%d\n", ansr);
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/10113397.html
Mex
今日推荐