zoukankan      html  css  js  c++  java
  • bzoj4763

    $分块$

    $一个很有趣的技巧$

    $在树上选sqrt(n)个关键点,每两个关键点之间的距离<=sqrt(n),每个关键点属于一条链$

    $预处理出每两个关键点的bitset$

    $每次询问就暴力向上爬,合并bitset$

    $由于要查询,所以要手写bitset$

     
    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    const int bl = 470, N = 1e5 + 5;
    ull Num[65537];
    vector<int> G[N];
    int n, m, f, bbl, last;
    ull Max;
    int fa[N][18], dep[N], mx[N], w[N], mark[N], top[N], mir[N];
    int read() {
        int x = 0, f = 1;
        char c = getchar();
        while(!isdigit(c)) {
            if(c == '-') {
                f = -1;
            }
            c = getchar();
        }
        while(isdigit(c)) {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x * f;
    }
    struct Bitset {
        int len;
        ull s[bl];
        void clear() {
            for(int i = 0; i <= len; ++i) {
                s[i] = 0;
            }
            len = 0;
        }
        void operator |= (const Bitset &a) {
            len = max(len, a.len);
            for(int i = 0; i <= len; ++i) {
                s[i] |= a.s[i];
            }
        }
        void operator |= (int b) {
            len = max(len, b >> 6);
            s[b >> 6] |= 1LL << (b & 63);
        }
        int num() {
            int ret = 0;
            for(int i = 0; i <= len; ++i) {
                ret += Num[s[i] >> 48] + Num[(s[i] >> 32) & 65535] + Num[(s[i] >> 16) & 65535] + Num[s[i] & 65535];
            }
            return ret;
        }
        int mex() {
            for(int i = 0; i <= len; ++i) {
                if(s[i] != Max) {
                    for(int j = 0; j < 64; ++j) {
                        if(!(s[i] & (1LL << j))) {
                            return i * 64 + j;
                        }
                    }
                }
            }
        }
    } b[350][350], ans;
    void dfs(int u) {
        mx[u] = dep[u];
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(v == fa[u][0]) {
                continue;
            }
            fa[v][0] = u;
            dep[v] = dep[u] + 1;
            dfs(v);
            mx[u] = max(mx[u], mx[v]);
        }
        if(mx[u] - dep[u] >= bbl || u == 1) {
            mark[u] = ++mark[0];
            mir[mark[u]] = u;
            mx[u] = 0;
        }
    }
    int lca(int u, int v) {
        if(dep[u] < dep[v]) {
            swap(u, v);
        }
        int d = dep[u] - dep[v];
        for(int i = 0; i < 18; ++i) {
            if(d & (1 << i)) {
                u = fa[u][i];
            }
        }
        if(u == v) {
            return u;
        } 
        for(int i = 17; i >= 0; --i) {
            if(fa[u][i] != fa[v][i]) {
                u = fa[u][i];
                v = fa[v][i];
            }
        }
        return fa[u][0];
    }
    int main() {
        n = read();
        m = read();
        f = read();
        bbl = sqrt(n);
        for(int i = 0; i < 64; ++i) {
            Max |= 1LL << i;
        }
        for(int i = 0; i < 65536; ++i) {
            for(int j = 0; j < 16; ++j) {
                if(i & (1 << j)) {
                    ++Num[i];
                }
            }
        }
        for(int i = 1; i <= n; ++i) {
            w[i] = read();
        }
        for(int i = 1; i < n; ++i) {
            int u = read(), v = read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dep[1] = 1;
        dfs(1);
        for(int j = 1; j <= 17; ++j) {
            for(int i = 1; i <= n; ++i) {
                fa[i][j] = fa[fa[i][j - 1]][j - 1];
            }
        }
        for(int i = 1; i <= mark[0]; ++i) {
            ans.clear();
            ans |= w[mir[i]];
            int x;
            b[i][i] |= w[mir[i]];
            for(x = fa[mir[i]][0]; x; x = fa[x][0]) {
                ans |= w[x];
                if(mark[x]) {
                    b[i][mark[x]] = ans;
                    if(!top[mir[i]]) {
                        top[mir[i]] = x;
                    }
                }
            }
        }
        while(m--) {
            int a = read(), x, y, z;
            ans.clear();
            while(a--) {
                x = read();
                y = read();
                if(f) {
                    x = x ^ last;
                    y = y ^ last;
                }
                ans |= w[x];
                ans |= w[y];
                z = lca(x, y);
                for(; x && !mark[x] && dep[x] > z; x = fa[x][0]) {
                    ans |= w[x];
                }
                for(; y && !mark[y] && dep[y] > z; y = fa[y][0]) {
                    ans |= w[y];
                }
                int xx, yy;
                for(xx = x; dep[top[xx]] >= dep[z]; xx = top[xx]);
                for(yy = y; dep[top[yy]] >= dep[z]; yy = top[yy]);
                ans |= b[mark[x]][mark[xx]];
                ans |= b[mark[y]][mark[yy]];
                for(x = xx; dep[x] >= dep[z]; x = fa[x][0]) {
                    ans |= w[x];
                }
                for(y = yy; dep[y] >= dep[z]; y = fa[y][0]) {
                    ans |= w[y];
                }
            }
            int ta = ans.num(), tb = ans.mex();
            last = ta + tb;
            printf("%d %d
    ", ta, tb);  
        }
        return 0;
    }
    View Code
  • 相关阅读:
    东南大学2020年数学分析考研试题参考解答
    东北师范大学2020年数学分析考研试题参考解答
    丁同仁常微分方程第一版习题参考解答
    电子科技大学2020年数学分析考研试题参考解答
    点集拓扑课件/作业/作业讲解
    毕业论文[博士]不可压缩流体动力学方程组的若干正则性条件
    毕业论文[本科]笛卡尔积上的拓扑学
    Ibragimov微分方程与数学物理问题习题参考解答
    Evans Partial Differential Equations 第一版第1-3章笔记及习题解答
    [Tex模板]Annales Polonici Mathematici
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8461930.html
Copyright © 2011-2022 走看看