大概是 O(wVmn) ?要不要再乘个 log 我不确定,因为树剖下来的区间是不交的。
就是直接树剖套分块,维护块内 bitset,然后散块暴力,整块直接或起来。
感觉这个复杂度很难绷,但是没卡就过了?建议加强数据。
#include <cmath>
#include <cstdio>
#include <bitset>
using namespace std;
struct E
{
int v, t;
} e[200050];
int n, m, c, p, K, L[512], R[512], T[100050], a[100050], z[100050],
d[100050], f[100050], s[100050], t[100050], b[100050], k[100050], h[100050];
bitset<30001> B[512];
bool F;
void A(int u, int v)
{
e[++c] = {v, h[u]};
h[u] = c;
}
void X(int u)
{
s[u] = 1;
for (int i = h[u], v; i; i = e[i].t)
if (!d[v = e[i].v])
{
d[v] = d[f[v] = u] + 1;
X(v);
s[u] += s[v];
if (s[v] > s[z[u]])
z[u] = v;
}
}
void Y(int u, int g)
{
t[k[b[u] = ++p] = u] = g;
if (z[u])
Y(z[u], g);
for (int i = h[u], v; i; i = e[i].t)
if ((v = e[i].v) != f[u] && v != z[u])
Y(v, v);
}
bitset<30001> Q(int l, int r)
{
bitset<30001> q;
if (T[l] == T[r])
{
for (int i = l; i <= r; ++i)
q[a[k[i]]] = 1;
return q;
}
for (int i = l; i <= R[T[l]]; ++i)
q[a[k[i]]] = 1;
for (int i = T[l] + 1; i < T[r]; ++i)
q |= B[i];
for (int i = L[T[r]]; i <= r; ++i)
q[a[k[i]]] = 1;
return q;
}
int main()
{
scanf("%d%d%d", &n, &m, &F);
K = sqrt(n);
for (int i = 1; i <= n; ++i)
scanf("%d", a + i);
for (int i = 1, u, v; i < n; ++i)
scanf("%d%d", &u, &v), A(u, v), A(v, u);
X(d[1] = 1);
Y(1, 1);
for (int i = 1; i <= n; ++i)
B[T[i] = (i - 1) / K + 1][a[k[i]]] = 1;
for (int i = 1; i <= T[n]; ++i)
L[i] = (i - 1) * K + 1, R[i] = min(i * K, n);
for (int i = 0, l = 0, r, o, x, y; i < m; ++i)
{
bitset<30001> q;
scanf("%d", &o);
while (o--)
{
scanf("%d%d", &x, &y);
if (F)
x ^= l, y ^= l;
while (t[x] != t[y])
{
if (d[t[x]] < d[t[y]])
swap(x, y);
q |= Q(b[t[x]], b[x]);
x = f[t[x]];
}
if (b[x] > b[y])
swap(x, y);
q |= Q(b[x], b[y]);
}
printf("%d %d\n", l = q.count(), r = (~q)._Find_first());
l += r;
}
return 0;
}