题解 P3603 【雪辉】
提供一种纯树剖+bitset的写法。
喜提洛谷最慢解。
怎么人均树分块啊,感觉我要被lxl卡了
【思路】
首先又是数颜色又是mex的,很容易想到bitset。
一种很naive的想法就是树剖,然后去暴力合并bitset。
(然而这种naive的做法稍微改一改居然能过。)
也就是对于树剖后建出来的那一棵线段树,每一个节点存一个 bitset 表示这个区间内的并集。
然后你会发现空间开不下。
考虑怎么节约空间。
我们不难发现线段树越深的节点存的信息越少,到最后一层干脆只有
于是考虑把线段树的最后两层割掉不用 bitset 维护,而用 pair 去维护。
这样空间缩小了四倍就可以卡过去了,最底下两层由于不用bitset,消耗空间相比之下基本可以忽略不计。
实现上由于要求 mex ,我用了手写 bitset 。
具体实现上其实也没什么特别的,线段树上合并信息就直接对两个 bitset 取或,然后就得到了一个 bitset 表示这些链的数集之并。
那么两个询问的结果都出来了,用 bitset 基本操作的 count 什么的乱搞一下就行了。
是在线的。
然后就一遍 A 了。
复杂度似乎是
所以我为什么能A啊。。。
【代码】
#include <cstdio>
#include <cstring>
#include <bits/stl_pair.h>
using std :: pair;
using std :: make_pair;
template <typename T>
inline void read(T &x){
x = 0;int fu = 1;
char c = getchar();
while(c > 57 || c < 48){
if(c == 45) fu = -1;
c = getchar();
}
while(c <= 57 && c >= 48){
x = (x << 3) + (x << 1) + c - 48;
c = getchar();
}
x *= fu;
}
template <typename T>
inline void fprint(T x){
if(x < 0) putchar(45), x = -x;
if(x > 9) fprint(x / 10);
putchar(x % 10 + 48);
}
template <typename T>
inline void fprint(T x, char ch){
fprint(x);putchar(ch);
}
#define MAXN 100005
typedef unsigned long long ULL;
int n, m, f;
const int V = 470;
const ULL MOD = 18446744073709551615ull;
struct Bitset{
ULL bit[475];
Bitset (){memset(bit, 0, sizeof(bit));}
inline void ins(int x){
bit[x >> 6] |= 1ull << (x & 63);
}
inline void del(int x){
bit[x >> 6] &= (MOD ^ 1ull << (x & 63));
}
inline void clear(){memset(bit, 0, sizeof(bit));}
inline Bitset operator | (const Bitset &b) const{
Bitset ret;
for (register int i = 0;i < V;i ++) ret.bit[i] = bit[i] | b.bit[i];
return ret;
}
inline int mex(){
for (register int i = 0;i < V;i ++){
if(bit[i] ^ MOD){
for (register int j = 0;j < 64;j ++){
if(!((bit[i] >> j) & 1)) return i << 6 | j;
}
}
}
}
inline int count(){
int ret = 0;
for (register int i = 0;i < V;i ++){ret += __builtin_popcountll(bit[i]);}
return ret;
}
}t[MAXN];
int a[MAXN];
#define LSON rt << 1, l, mid
#define RSON rt << 1 | 1, mid + 1, r
typedef pair <int, int> pi;
pi val[MAXN << 2];
int b[MAXN], dep[MAXN], sz[MAXN], fa[MAXN], son[MAXN], id[MAXN], tp[MAXN];
int head[MAXN], e[MAXN << 1], nxt[MAXN << 1], cnt;
inline void add(int u, int v){
nxt[++ cnt] = head[u];
head[u] = cnt;
e[cnt] = v;
}
void dfs1(int x, int pre){
fa[x] = pre;dep[x] = dep[pre] + 1;sz[x] = 1;
for (register int i = head[x];i;i = nxt[i]){
if(e[i] == pre) continue;
dfs1(e[i], x);
sz[x] += sz[e[i]];
if(sz[e[i]] > sz[son[x]]) son[x] = e[i];
}
}
int tot;
void dfs2(int x, int tt){
tp[x] = tt;id[x] = ++ tot;b[tot] = a[x];
if(son[x]) dfs2(son[x], tt);
for (register int i = head[x];i;i = nxt[i]){
if(e[i] == son[x] || e[i] == fa[x]) continue;
dfs2(e[i], e[i]);
}
}
inline void pushup(int rt, int l, int r){
if(r - l + 1 <= 2){
val[rt].first = val[rt << 1].first;
val[rt].second = val[rt << 1 | 1].first;
}
else {
int mid = (l + r) >> 1;
if(mid - l + 1 <= 2) {
t[rt].clear();
if(~val[rt << 1].first) t[rt].ins(val[rt << 1].first);
if(~val[rt << 1].second) t[rt].ins(val[rt << 1].second);
}
else t[rt] = t[rt << 1];
if(r - mid <= 2){
if(~val[rt << 1 | 1].first) t[rt].ins(val[rt << 1 | 1].first);
if(~val[rt << 1 | 1].second) t[rt].ins(val[rt << 1 | 1].second);
}
else t[rt] = t[rt] | t[rt << 1 | 1];
}
}
#define LSON rt << 1, l, mid
#define RSON rt << 1 | 1, mid + 1, r
void build(int rt, int l, int r){
if(l == r){
val[rt].first = b[l];
val[rt].second = -1;
return ;
}
int mid = (l + r) >> 1;
build(LSON);build(RSON);
pushup(rt, l, r);
}
pi Query(int rt, int l, int r, int x, int y){
if(x <= l && r <= y) return val[rt];
int mid = (l + r) >> 1;
if(x <= mid && y > mid) return make_pair(Query(LSON, x, y).first, Query(RSON, x, y).first);
if(x <= mid) return Query(LSON, x, y);
else return Query(RSON, x, y);
}
Bitset query(int rt, int l, int r, int x, int y){
if(x <= l && r <= y){
if(r - l + 1 <= 2) {
Bitset ret;
if(~val[rt].first) ret.ins(val[rt].first);
if(~val[rt].second) ret.ins(val[rt].second);
return ret;
}
else return t[rt];
}
Bitset ret;
int mid = (l + r) >> 1;
if(x <= mid) ret = query(LSON, x, y);
if(y > mid) ret = ret | query(RSON, x, y);
return ret;
}
Bitset QUERY(int u, int v){
Bitset ret;
while(tp[u] ^ tp[v]){
if(dep[tp[u]] < dep[tp[v]]) u ^= v ^= u ^= v;
if(id[u] - id[tp[u]] + 1 <= 2){
pi res = Query(1, 1, n, id[tp[u]], id[u]);
if(~res.first) ret.ins(res.first);
if(~res.second) ret.ins(res.second);
}
else ret = ret | query(1, 1, n, id[tp[u]], id[u]);
u = fa[tp[u]];
}
if(id[u] > id[v]) u ^= v ^= u ^= v;
if(id[v] - id[u] + 1 <= 2){
pi res = Query(1, 1, n, id[u], id[v]);
if(~res.first) ret.ins(res.first);
if(~res.second) ret.ins(res.second);
}
else ret = ret | query(1, 1, n, id[u], id[v]);
return ret;
}
int ans;
int main(){
read(n);read(m);read(f);
for (register int i = 1;i <= n;i ++) read(a[i]);
for (register int i = 1;i < n;i ++){
int u, v;read(u);read(v);
add(u, v);add(v, u);
}
dfs1(1, 0);dfs2(1, 1);
build(1, 1, n);
while(m --){
ans *= f;
int k, u, v;
Bitset ret;read(k);
while(k --){
read(u);read(v);u ^= ans, v ^= ans;
ret = ret | QUERY(u, v);
}
int num1 = ret.mex(), num2 = ret.count();
ans = num1 + num2;
fprint(num2, 32);fprint(num1, 10);
}
}