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\n", ta, tb);  
    }
    return 0;
}
View Code

 

posted @ 2018-02-23 14:36  19992147  阅读(103)  评论(0编辑  收藏  举报