我没想到省选 day2 宝石还可以用分块,话说当时我旁边的哥们就打了一个树分块……
分块是个极不优美的做法,难写的离谱……(当然莫队系列除外
P6177 Count on a tree II/【模板】树分块
本题强制在线。所以莫队被废了
看到题目让求路径颜色数,考虑复杂度比较高的分块做法(话说我一开始想的是树上主席树
树分块有很多分块方式
跟据罗剑桥的国家集训队论文,我算是勉强掌握了一种。
在树上撒(sqrt n)个关键点,要求对于每个非关键点,它的(1-sqrt n)级祖先中,必定存在至少一个关键点。
容易知道每存在一个关键点能保证最少存在(sqrt n)个非关键点,那么全局最多有(sqrt n)个关键点
而且若是沿着一个关键点向上跳,则最多跳大概(Theta(sqrt n))就会达到最靠近根节点的关键点。
首先花费(O(nsqrt n))预处理所有关键点,然后花费(O(frac{n^2sqrt n}{w}))预处理任意两个关键点之间的颜色(用bitset
考虑询问u,v两个点,先求出lca,然后求出离他们最近的关键点。之后关键点之间的颜色数直接调用预处理,关键点与u和v之间的颜色直接暴力即可
总复杂度(O(frac{qnsqrt n}{w}))
#include <bits/stdc++.h>
using namespace std;
#define INF 1<<30
#define pb push_back
%:define ill unsigned long long
%:define lowbit(x) (x&(-x))
%:define Int unsigned int
const int np = 4e4 + 5;
template<typename _T>
inline void read(_T &x)
{
x = 0;int f= 1;char s = getchar();
while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
x*=f;
}
int head[np] , nxt[np * 2] , ver[np * 2];
int tit;
inline void add(int x,int y)
{
ver[++tit] = y;
nxt[tit] = head[x];
head[x] = tit;
}
int dep[np];
int val[np];
int pos[np];
int b[np];
int key[np],fkey[np];
int fa[np],son[np],siz[np];
bitset<np> bit[59][59];
int Top[np];
inline bool cmp(int a,int b)
{
return dep[a] > dep[b];
}
inline void dfs_key(int x,int ff)
{
dep[x] = dep[ff] + 1;
fa[x] = ff;
siz[x] = 1;
for(int i=head[x],v;i;i=nxt[i])
{
v =ver[i];
if(v == ff) continue;
dfs_key(v,x);
siz[x] += siz[v];
if(siz[v] > siz[son[x]]) son[x] =v;
}
}
inline void dfs_pf(int x,int anc,int k_)
{
if(key[x] && k_ != x) fkey[x] = k_,k_ = x;
Top[x] = anc;
if(son[x]) dfs_pf(son[x] , anc,k_);
for(int i=head[x],v;i;i=nxt[i])
{
v = ver[i];
if(v == fa[x] || v == son[x]) continue;
dfs_pf(v,v,k_);
}
}
inline int LCA(int x,int y)
{
int fx = Top[x] ,fy = Top[y];
while(fx != fy)
{
if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
x = fa[fx];
fx = Top[x];
}
return dep[x] < dep[y]?x:y;
}
bitset<np> bi;
inline void dfs_(int x,int k_,int ff)
{
int posb = bi[val[x]];
bi[val[x]] = 1;
if(key[x])
{
if(key[x] >= k_)bit[k_][key[x]] = bit[key[x]][k_] = bi;
}
for(int i=head[x],v;i;i=nxt[i])
{
v =ver[i];
if(v == ff) continue;
dfs_(v,k_,x);
}
if(!posb) bi[val[x]] = 0;
}
inline int debug()
{
return 1;
}
int T;
int n,m;
int key_[np];
signed main()
{
// cout<<(4e4 /700);// * (4e4/600) * 4e4/1024/1024;
// freopen("foo.in","r",stdin);
// freopen("my.out","w",stdout);
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
read(n);
read(m);
// T = sqrt(n);
T = 700;
for(int i=1;i<=n;i++) read(val[i]);
memcpy(b +1,val +1 ,sizeof(val));
sort(b + 1,b + 1 +n);
int *st = b +1 ;
int *ed = unique(b + 1,b +1 +n);
for(int i=1;i<=n;i++) val[pos[i] = i] = lower_bound(st,ed,val[i])-b;
for(int i=1,x,y;i<=n - 1;i++)
{
read(x);
read(y);
add(x,y);
add(y,x);
}
dfs_key(1,0);
sort(pos + 1,pos + 1 + n,cmp);
// for(int i=1;i<=n;i++) cout<<pos[i]<<" ";
// cout<<'
';
for(int i=1;i<=n;i++)
{
int x = fa[pos[i]];
if(!x) continue;
int g=x;
for(int j=1;j<=T;j++)
{
if(key[x]) break;
if(!fa[x]) {
key[x] = 1;
break;
}
g =x;
x = fa[x];
}
if(key[x]) continue;
key[g] = 1;
}
int top =0 ;
for(int i=1;i<=n;i++) if(key[i]) key_[++top] = i;
if(!key[1]) key[1] = 1,key_[++top] = 1;
for(int i=1;i<=top;i++)
{
key[key_[i]] = i;
}
// cout<<"*";
for(int i=1;i<=top;i++)
dfs_(key_[i],i,0) , bi.reset();
// return 0;
dfs_pf(1,1,1);
int u,v,la =0 ;
// for(int i=1;i<=top;i++) cout<<key_[i]<<" "<<key[key_[i]]<<'
';
// cout<<'
';
// for(int i=1;i<=top;i++)
// {
// for(int j=1;j<=top;j++)
// {
// int opi = bit[i][j].count();
//// cout<<i<<" "<<j<<" "<<opi<<'
';
// }
// }
// return 0;
bi.reset();
int h = 1;
while(m--)
{
// if(h == 2944) debug();
read(u);
read(v);
// read(la);
// int num = bi.count();
u = u ^ la;
int lca = LCA(u,v);
int u_ = u,v_ = v;
while(!key[u_] && u_ != lca) bi[val[u_]] = 1,u_ = fa[u_];
while(!key[v_] && v_ != lca) bi[val[v_]] = 1,v_ = fa[v_];
if(u_ != lca)
{
int cu = u_;
while(dep[fkey[u_]] > dep[lca]) u_ = fkey[u_];/*if(fkey[u_] == u_) break;*/
bi |= bit[key[u_]][key[cu]];
while(u_ != lca) bi[val[u_]] = 1,u_ = fa[u_];
}
if(v_ != lca)
{
int cv = v_;
while(dep[fkey[v_]] > dep[lca]) v_ = fkey[v_];/*if(fkey[v_] == v_) break;*/
bi |= bit[key[v_]][key[cv]];
while(v_ != lca) bi[val[v_]] = 1,v_ = fa[v_];
}
bi[val[lca]] = 1;
u = bi.count();
printf("%d
",u);
// cout<<u<<'
';
bi.reset();
la = u;
h++;
}
return 0;
}