「BZOJ4763」雪辉

「BZOJ4763」天野雪辉

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

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

另外 \(\text{bitset}\) 好像不太支持找 \(mex\) 不过可以手写或者选择下划线开头的函数 \(\text{_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('\n');
    }
    flush();
    return 0;
}
posted @ 2019-02-20 15:50  Joyemang33  阅读(241)  评论(0编辑  收藏  举报