题意:给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex
mex就是一个集合中最小的没有出现的非负整数,注意0要算
rand出 (sqrt n)个点,把每次查询拆成 x->fx0->fx->lca->fy->fy0->y
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
template<typename T> void read(T & x) {
int c = getchar(); x = 0;
while(!isdigit(c)) c = getchar();
while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define read2(a, b) (read(a), read(b))
#define read3(a, b, c) (read(a), read2(b, c))
const int MAXN = 100007;
struct Edge{
int v, next;
}G[MAXN<<1]; int tot, head[MAXN], dq[MAXN], n, q, siz[MAXN], dep[MAXN], top[MAXN], anc[MAXN], son[MAXN], cnt[1<<16], s, m, u, v, up[MAXN], pos[357], lca, b, tpos[MAXN];
bool vis[MAXN], f;
int _popcount(int x) {
static int ret;
for(ret = 0; x; ret += x & 1, x >>= 1);
return ret;
}
int popcount(ull x) {
static int ret = 0;
for(ret = 0; x; ret += cnt[x & 0xffff], x >>= 16);
return ret;
}
inline void chmax(int &x, int y) {if (x < y) x = y;}
struct Bitset{
static const ull ful = 0xffffffffffffffff;
ull bit[470]; int len, Mex, Num;
void reset() {for(int i = 0; i <= len; ++i) bit[i] = 0; len = 0; Num = Mex = 0;}
void operator |= (const Bitset &rhs) {
chmax(len, rhs.len);
for(int i = 0; i <= len; ++i) bit[i] |= rhs.bit[i];
}
void operator |= (int x) {
chmax(len, x >> 6);
bit[x >> 6] |= 1ull << (x & 63);
}
int mex() {
for(int i = 0; i <= len; ++i)
if (bit[i] != ful)
for(int j = 0; j < 64; ++j) if (!(bit[i] & (1ull<<j))) return Mex = i * 64 + j;
}
int num() {
for(int i = 0; i <= len; ++i)
Num += popcount(bit[i]);
return Num;
}
}dis[353][351], t;
void add(int u, int v) {G[++tot] = (Edge){v, head[u]}; head[u] = tot;}
#define v G[i].v
void dfs1(int u) {
dep[u] = dep[anc[u]] + 1;
siz[u] = 1;
for(int i = head[u]; i; i = G[i].next) {
if (v == anc[u]) continue;
anc[v] = u;
dfs1(v), siz[u] += siz[v];
if (siz[son[u]] <= siz[v]) son[u] = v;
}
}
void dfs2(int u, int t) {
top[u] = t;
if (son[u]) dfs2(son[u], t);
for(int i = head[u]; i; i = G[i].next)
if (v != son[u] && v != anc[u]) dfs2(v, v);
}
#undef v
int LCA(int u, int v) {
while(top[u] != top[v])
dep[top[u]] >= dep[top[v]] ? u = anc[top[u]] : v = anc[top[v]];
return dep[u] < dep[v] ? u : v;
}
#define u1(x) while(!vis[x] && x != lca) t |= dq[x], x = anc[x];
#define u3(x) while(x != lca) t |= dq[x], x = anc[x];
void u2(int &x) {
int nx = x;
while(dep[up[x]] > dep[lca]) x = up[x];
t |= dis[tpos[nx]][tpos[x]];
}
void update() {
u1(u); u1(v);
u2(u); u2(v);
u3(u); u3(v);
}
int main(void) {
// freopen("data.in", "r", stdin);
for(int i = 0; i < (1<<16); ++i) cnt[i] = _popcount(i);
read3(n, m, f);
for(int i = 1; i <= n; ++i) read(dq[i]);
for(int i = 1; i < n; ++i) read2(u, v), add(u, v), add(v, u);
dfs1(1);
dfs2(1, 1);
s = sqrt(n);
for(int i = 1; i <= s; ++i) {
do q = rand()%n+1;while(vis[q]);
vis[q] = 1, tpos[pos[i] = q] = i;
}
for(int i = 1; i <= s; ++i) {
int u = pos[i]; t.reset();
while(u){
t |= dq[u];
if (vis[u] && u != pos[i]) {
dis[i][tpos[u]] |= t;
if (!up[pos[i]]) up[pos[i]] = u;
}
u = anc[u];
}
}
int last = 0;
while(m--) {
t.reset(); read(b);
while(b--) {
read2(u, v);
if (f) u ^= last, v ^= last;
lca = LCA(u, v), t |= dq[lca];
update();
}
last = t.num()+t.mex();
printf("%d %d
", t.Num, t.Mex);
}
return 0;
}