1 条题解

  • 0
    @ 2025-8-24 21:50:38

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar DPair
    その真っ白な心に、これからたくさんの思い出を。未来を想い、少女は少年に名を赠る。

    搬运于2025-08-24 21:50:38,当前版本为作者最后更新于2020-12-11 20:20:38,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    提供一种纯树剖+bitset的写法。

    喜提洛谷最慢解。

    怎么人均树分块啊,感觉我要被lxl卡了

    【思路】

    首先又是数颜色又是mex的,很容易想到bitset。

    一种很naive的想法就是树剖,然后去暴力合并bitset。

    (然而这种naive的做法稍微改一改居然能过。)

    也就是对于树剖后建出来的那一棵线段树,每一个节点存一个 bitset 表示这个区间内的并集。

    然后你会发现空间开不下。

    考虑怎么节约空间。

    我们不难发现线段树越深的节点存的信息越少,到最后一层干脆只有 11 个数了。

    于是考虑把线段树的最后两层割掉不用 bitset 维护,而用 pair 去维护。

    这样空间缩小了四倍就可以卡过去了,最底下两层由于不用bitset,消耗空间相比之下基本可以忽略不计。

    实现上由于要求 mex ,我用了手写 bitset 。

    具体实现上其实也没什么特别的,线段树上合并信息就直接对两个 bitset 取或,然后就得到了一个 bitset 表示这些链的数集之并。

    那么两个询问的结果都出来了,用 bitset 基本操作的 count 什么的乱搞一下就行了。

    是在线的。

    然后就一遍 A 了。

    复杂度似乎是 O(nVlog2nw)O({nV\log^2n \over w}) 的?

    所以我为什么能A啊。。。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <bits/stl_pair.h>
    using std :: pair;
    using std :: make_pair;
    template <typename T>
    inline void read(T &x){
        x = 0;int fu = 1;
        char c = getchar();
        while(c > 57 || c < 48){
            if(c == 45) fu = -1;
            c = getchar();
        }
        while(c <= 57 && c >= 48){
            x = (x << 3) + (x << 1) + c - 48;
            c = getchar();
        }
        x *= fu;
    }
    template <typename T>
    inline void fprint(T x){
        if(x < 0) putchar(45), x = -x;
        if(x > 9) fprint(x / 10);
        putchar(x % 10 + 48);
    }
    template <typename T>
    inline void fprint(T x, char ch){
        fprint(x);putchar(ch);
    }
    
    #define MAXN 100005
    typedef unsigned long long ULL;
    int n, m, f;
    const int V = 470;
    const ULL MOD = 18446744073709551615ull;
    struct Bitset{
        ULL bit[475];
        Bitset (){memset(bit, 0, sizeof(bit));}
        inline void ins(int x){
            bit[x >> 6] |= 1ull << (x & 63);
        }
        inline void del(int x){
            bit[x >> 6] &= (MOD ^ 1ull << (x & 63));
        }
        inline void clear(){memset(bit, 0, sizeof(bit));}
        inline Bitset operator | (const Bitset &b) const{
            Bitset ret;
            for (register int i = 0;i < V;i ++) ret.bit[i] = bit[i] | b.bit[i];
            return ret;
        }
        inline int mex(){
            for (register int i = 0;i < V;i ++){
                if(bit[i] ^ MOD){
                    for (register int j = 0;j < 64;j ++){
                        if(!((bit[i] >> j) & 1)) return i << 6 | j;
                    }
                }
            }
        }
        inline int count(){
            int ret = 0;
            for (register int i = 0;i < V;i ++){ret += __builtin_popcountll(bit[i]);}
            return ret;
        }
    }t[MAXN];
    int a[MAXN];
    
    #define LSON rt << 1, l, mid
    #define RSON rt << 1 | 1, mid + 1, r
    typedef pair <int, int> pi;
    pi val[MAXN << 2];
    int b[MAXN], dep[MAXN], sz[MAXN], fa[MAXN], son[MAXN], id[MAXN], tp[MAXN];
    int head[MAXN], e[MAXN << 1], nxt[MAXN << 1], cnt;
    inline void add(int u, int v){
        nxt[++ cnt] = head[u];
        head[u] = cnt;
        e[cnt] = v;
    }
    void dfs1(int x, int pre){
        fa[x] = pre;dep[x] = dep[pre] + 1;sz[x] = 1;
        for (register int i = head[x];i;i = nxt[i]){
            if(e[i] == pre) continue;
            dfs1(e[i], x);
            sz[x] += sz[e[i]];
            if(sz[e[i]] > sz[son[x]]) son[x] = e[i];
        }
    }
    int tot;
    void dfs2(int x, int tt){
        tp[x] = tt;id[x] = ++ tot;b[tot] = a[x];
        if(son[x]) dfs2(son[x], tt);
        for (register int i = head[x];i;i = nxt[i]){
            if(e[i] == son[x] || e[i] == fa[x]) continue;
            dfs2(e[i], e[i]);
        }
    }
    inline void pushup(int rt, int l, int r){
        if(r - l + 1 <= 2){
            val[rt].first = val[rt << 1].first;
            val[rt].second = val[rt << 1 | 1].first;
        }
        else {
            int mid = (l + r) >> 1;
            if(mid - l + 1 <= 2) {
                t[rt].clear();
                if(~val[rt << 1].first) t[rt].ins(val[rt << 1].first);
                if(~val[rt << 1].second) t[rt].ins(val[rt << 1].second);
            }
            else t[rt] = t[rt << 1];
            if(r - mid <= 2){
                if(~val[rt << 1 | 1].first) t[rt].ins(val[rt << 1 | 1].first);
                if(~val[rt << 1 | 1].second) t[rt].ins(val[rt << 1 | 1].second);
            }
            else t[rt] = t[rt] | t[rt << 1 | 1];
        }
    }
    
    #define LSON rt << 1, l, mid
    #define RSON rt << 1 | 1, mid + 1, r
    
    void build(int rt, int l, int r){
        if(l == r){
            val[rt].first = b[l];
            val[rt].second = -1;
            return ;
        }
        int mid = (l + r) >> 1;
        build(LSON);build(RSON);
        pushup(rt, l, r);
    }
    
    pi Query(int rt, int l, int r, int x, int y){
        if(x <= l && r <= y) return val[rt];
        int mid = (l + r) >> 1;
        if(x <= mid && y > mid) return make_pair(Query(LSON, x, y).first, Query(RSON, x, y).first);
        if(x <= mid) return Query(LSON, x, y);
        else return Query(RSON, x, y);
    }
    
    Bitset query(int rt, int l, int r, int x, int y){
        if(x <= l && r <= y){
            if(r - l + 1 <= 2) {
                Bitset ret;
                if(~val[rt].first) ret.ins(val[rt].first);
                if(~val[rt].second) ret.ins(val[rt].second);
                return ret;
            }
            else return t[rt];
        }
        Bitset ret;
        int mid = (l + r) >> 1;
        if(x <= mid) ret = query(LSON, x, y);
        if(y > mid) ret = ret | query(RSON, x, y);
        return ret;
    }
    Bitset QUERY(int u, int v){
        Bitset ret;
        while(tp[u] ^ tp[v]){
            if(dep[tp[u]] < dep[tp[v]]) u ^= v ^= u ^= v;
            if(id[u] - id[tp[u]] + 1 <= 2){
                pi res = Query(1, 1, n, id[tp[u]], id[u]);
                if(~res.first) ret.ins(res.first);
                if(~res.second) ret.ins(res.second);
            }
            else ret = ret | query(1, 1, n, id[tp[u]], id[u]);
            u = fa[tp[u]];
        }
        if(id[u] > id[v]) u ^= v ^= u ^= v;
        if(id[v] - id[u] + 1 <= 2){
            pi res = Query(1, 1, n, id[u], id[v]);
            if(~res.first) ret.ins(res.first);
            if(~res.second) ret.ins(res.second);
        }
        else ret = ret | query(1, 1, n, id[u], id[v]);
        return ret;
    }
    int ans;
    int main(){
        read(n);read(m);read(f);
        for (register int i = 1;i <= n;i ++) read(a[i]);
        for (register int i = 1;i < n;i ++){
            int u, v;read(u);read(v);
            add(u, v);add(v, u);
        }
        dfs1(1, 0);dfs2(1, 1);
        build(1, 1, n);
        while(m --){
            ans *= f;
            int k, u, v;
            Bitset ret;read(k);
            while(k --){
                read(u);read(v);u ^= ans, v ^= ans;
                ret = ret | QUERY(u, v);
            }
            int num1 = ret.mex(), num2 = ret.count();
            ans = num1 + num2;
            fprint(num2, 32);fprint(num1, 10);
        }
    }
    
    • 1

    信息

    ID
    2675
    时间
    3000ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者