zoukankan      html  css  js  c++  java
  • 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
    ", ansr);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    如何优雅地用Redis实现分布式锁?
    redis 持久化有几种方式?
    怎么保证缓存和数据库数据的一致性?
    jedis 和 redisson 有哪些区别?
    redis支持哪些数据类型?redis命令大全
    什么是redis的缓存雪崩与缓存穿透?如何解决?
    redis 为什么是单线程的?
    什么是memecache?redis 和 memecache 有什么区别?
    Redis入门到精通(九)——Redis数据库基本操作(切换数据库,数据移动,删除数据)
    Redis入门到精通(八)——key通用指令基本操作、key扩展操作(时效性控制、查询模式)、key其他操作(为key改名)
  • 原文地址:https://www.cnblogs.com/MingSD/p/10113397.html
Copyright © 2011-2022 走看看