• 「BZOJ4763」雪辉


    「BZOJ4763」天野雪辉

    题目大意:有一棵 (n) 个点的树,树上每一个点有权值 (a_i leq 30000) ,每次询问给出若干路径,求出这些路径的并上面的不同颜色数与 (mex)(n ,mleq 10^5)

    解题思路:solution1:直接树分块,每个点维护其到第一个关键祖先的一个 ( ext{bitset}) 并暴力添加两端的答案。solution2:对树的括号序列分块,把左括号看做 (1) ,右括号看做 (-1)。维护出任意两个块之间的 ( ext{bitset}),暴力添加两端的答案。由于不能保证任意时刻每个颜色的数量非负,所以还要在对于每个块的前缀维护个桶来记录颜色当前的数量,方便两端暴力加颜色时维护答案,复杂度都是 (O(msqrt{n}+frac{30000m}{w}))

    另外 ( ext{bitset}) 好像不太支持找 (mex) 不过可以手写或者选择下划线开头的函数 ( ext{_Find_first()})

    code

    /*program by mangoyang*/
    #pragma GCC optimize("Ofast","inline","-ffast-math")
    #pragma GCC target("avx,sse2,sse3,sse4,mmx")
    #include<bits/stdc++.h>
    #define rint register int
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    namespace FastIO{
        inline char read() {
            static const int IN_LEN = 1000000;
            static char buf[IN_LEN], *s, *t;
            return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin),(s == t ? -1 : *s++) : *s++);
        }
        template<class T>
        inline void read(T &x) {
            static bool iosig;
            static char c;
            for(iosig = false, c = read(); !isdigit(c); c = read()) {
                if (c == '-') iosig = true;
                if (c == -1) return;
            }
            for(x = 0; isdigit(c); c=read()) x = ((x + (x << 2)) << 1) + (c ^ '0');
            if(iosig) x = - x;
        }
        const int OUT_LEN = 10000000;
        char obuf[OUT_LEN], *ooh = obuf;
        inline void print(char c) {
            if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf;
            *ooh++=c;
        }
        template<class T>
        inline void print(T x) {
            static int buf[30], cnt;
            if(x == 0) print('0');
            else{
                if(x < 0) print('-'), x = -x;
                for(cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
                while(cnt) print((char)buf[cnt--]);
            }
        }
        inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }
    }
    using namespace FastIO;
    const int N = 200005, M = 30000, SZ = 347;
    #define fi first
    #define se second
    bitset<M+1> Ans[SZ][SZ];
    int ldfn[N], rdfn[N], ql[N], qr[N], tmp[M+1], buf[SZ][M+1], a[N], n, m, op, Size, block; 
    namespace tree{
        vector<int> g[N];
        int f[N][18], dep[N], cnt;
        inline void dfs(int u, int fa){
            ldfn[u] = ++cnt, ql[cnt] = a[u], qr[cnt] = 1;
            f[u][0] = fa, dep[u] = dep[fa] + 1;
            for(int i = 1; i <= 17; i++) f[u][i] = f[f[u][i-1]][i-1];
            for(int i = 0; i < g[u].size(); i++) 
                if(g[u][i] != fa) dfs(g[u][i], u);
            rdfn[u] = ++cnt, ql[cnt] = a[u], qr[cnt] = -1;
        }
        inline int lca(int x, int y){
            if(dep[x] < dep[y]) swap(x, y);
            for(int i = 17; ~i; i--) 
                if(dep[f[x][i]] >= dep[y]) x = f[x][i];
            if(x == y) return x;
            for(int i = 17; ~i; i--)
                if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
            return f[x][0];
        }
    }
    #define bel(x) ((x - 1) / Size + 1)
    #define L(x) ((x - 1) * Size + 1)
    #define R(x) (Min(x * Size, n))
    inline bitset<M+1> query(int l, int r){
        bitset<M+1> res;
        if(bel(l) + 1 >= bel(r)){
            for(rint i = l; i <= r; i++){
                if(!tmp[ql[i]] && ~qr[i]) res[ql[i]] = 1;
                else if(tmp[ql[i]] == 1 && qr[i] == -1) res[ql[i]] = 0; 
                tmp[ql[i]] += qr[i];
            }
            for(rint i = l; i <= r; i++) tmp[ql[i]] = 0;
            return res;
        }
        int lx = bel(l) + 1, rx = bel(r) - 1; res = Ans[lx][rx];
        for(rint i = l; i < L(lx); i++){
            if(!(tmp[ql[i]] + buf[rx][ql[i]] - buf[lx-1][ql[i]]) && ~qr[i]) res[ql[i]] = 1;
            else if((tmp[ql[i]] + buf[rx][ql[i]] - buf[lx-1][ql[i]]) == 1 && qr[i] == -1) res[ql[i]] = 0; 
            tmp[ql[i]] += qr[i];
        }
        for(rint i = R(rx) + 1; i <= r; i++){
            if(!(tmp[ql[i]] + buf[rx][ql[i]] - buf[lx-1][ql[i]]) && ~qr[i]) res[ql[i]] = 1;
            else if((tmp[ql[i]] + buf[rx][ql[i]] - buf[lx-1][ql[i]]) == 1 && qr[i] == -1) res[ql[i]] = 0; 
            tmp[ql[i]] += qr[i];
        }    
        for(rint i = l; i < L(lx); i++) tmp[ql[i]] = 0;
        for(rint i = R(rx) + 1; i <= r; i++) tmp[ql[i]] = 0; 
        return res;
    }
    signed main(){
        read(n), read(m), read(op);
        for(int i = 1; i <= n; i++) read(a[i]);
        for(int i = 1, x, y; i < n; i++){
            read(x), read(y);
            tree::g[x].push_back(y), tree::g[y].push_back(x);
        }
        tree::dfs(1, 0), n <<= 1;
        Size = 580, block = n / Size + ((n % Size) ? 1 : 0); 
        for(int i = 1; i <= n; i++) buf[bel(i)][ql[i]] += qr[i];
        for(int i = 2; i <= block; i++)
            for(int j = 0; j <= M; j++) buf[i][j] += buf[i-1][j];
        for(int i = 1; i <= block; i++){
            bitset<M+1> now;
            for(int j = L(i); j <= n; j++){
                if(bel(j) != bel(j-1) && bel(j) > i) Ans[i][bel(j)-1] = now;
                int x = ql[j], y = qr[j];
                if(tmp[x] <= 0 && tmp[x] + y > 0) now[x] = 1;
                if(tmp[x] > 0 && tmp[x] + y <= 0) now[x] = 0;
                tmp[x] += y;
            }
            Ans[i][Size] = now, memset(tmp, 0, sizeof(tmp));
        }
        int lastans = 0; 
        for(rint i = 1, x, y, num; i <= m; i++){
            read(num); bitset<M+1> res;
            for(rint j = 1; j <= num; j++){
                read(x), x ^= (lastans * op), read(y), y ^= (lastans * op);
                int lca = tree::lca(x, y);
                res |= query(ldfn[lca], ldfn[x]) | query(ldfn[lca], ldfn[y]); 
            }
            int ans1 = res.count(), ans2 = (ans1 == M + 1 ? M + 1 : 0);
            if(!ans2) res.flip(), ans2 = res._Find_first();
            lastans = ans1 + ans2;
            print(ans1), print(' '), print(ans2), print('
    ');
        }
        flush();
        return 0;
    }
    
  • 相关阅读:
    css选择器中的*= , |= , ^= , $= , ~= 的区别
    css 实现小三角
    使用vitevue3ts快速上手做一个todolist
    什么是回流和重绘?
    vue好用组件推荐
    Vue代码风格及规范
    聊聊 SpringBoot 中的两种占位符:@*@ 和 ${*}
    Maven 依赖调解源码解析(三):传递依赖,路径最近者优先
    Maven 依赖调解源码解析(二):如何调试 Maven 源码和插件源码
    Maven 依赖调解源码解析(五):同一个文件内声明,后者覆盖前者
  • 原文地址:https://www.cnblogs.com/mangoyang/p/10407125.html
Copyright © 2020-2023  润新知