树上莫队
无修改的分块
分块方法用王室联邦的方法
至于复杂度分析我不会….. 毕竟SB选手
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
int Blo[1000001];
int Cap[1000001];
struct Query
{
int u,v,a,b,no,ans;
inline void Bg()
{Blo[u]>Blo[v]?swap(u,v):swap(u,v),swap(u,v);}
inline friend bool operator <(Query a,Query b)
{return Blo[a.u]^Blo[b.u]?Blo[a.u]<Blo[b.u]:Blo[a.v]<Blo[b.v];}
}L[1000001];
inline bool cmp(Query a,Query b)
{return a.no<b.no;}
int B;
int F[100001][20];
int size[1000001];
struct Chain
{
int u;
Chain *next;
Chain(){next=NULL;}
}*Head[1000001];
inline void Add(int a,int b)
{
Chain *tp=new Chain;
tp->u=b;
tp->next=Head[a];
Head[a]=tp;
}
int dep[1000001];
int Cache[1000001],f[1000001];
int tot,con;
void DFS(int u,int fa)
{
f[u]=fa;
for(Chain *tp=Head[u];tp;tp=tp->next)
if(tp->u!=fa)
{
dep[tp->u]=dep[u]+1;
DFS(tp->u,u);
if(tot>=B)
{
++con;
while(tot)
Blo[Cache[tot--]]=con;
}
}
Cache[++tot]=u;
}
int root,ans;
int Cnt[1000001],color[1000001];
bool vis[1000001];
inline void NodeXor(int a)
{
if(vis[a])
{
vis[a]=false;
Cnt[color[a]]--;
if(!Cnt[color[a]])
ans--;
}
else
{
vis[a]=true;
Cnt[color[a]]++;
if(Cnt[color[a]]==1)
ans++;
}
}
inline void PathXor(int a,int b)
{
while(a^b)
{
if(dep[a]<dep[b])swap(a,b);
NodeXor(a);
a=f[a];
}
}
int LCA(int a,int b)
{
int j;
while(dep[a]^dep[b])
{
if(dep[a]<dep[b])swap(a,b);
for(j=0;dep[F[a][j+1]]>dep[b];j++);
a=F[a][j];
}
while(a^b)
{
for(j=0;F[a][j+1]^F[b][j+1];j++);
a=F[a][j],b=F[b][j];
}
return a;
}
int main()
{
int i,j,n,m,k;
read(n),read(m);
B=sqrt(n);
root=0;
for(i=1;i<=n;i++)
read(color[i]);
for(i=1;i<=n;i++)
{
read(j),read(k);
if(j==0||k==0)
root=j==0?k:j;
else Add(j,k);Add(k,j);
}
DFS(root,root);
for(j=1;j<=n;j++)
F[j][0]=f[j];
for(i=1;i<=19;i++)
for(j=1;j<=n;j++)
F[j][i]=F[F[j][i-1]][i-1];
++con;
while(tot)
Blo[Cache[tot--]]=con;
for(i=1;i<=m;i++)
read(L[i].u),read(L[i].v),read(L[i].a),read(L[i].b),L[i].no=i,L[i].Bg();
sort(L+1,L+1+m);
// NodeXor(root);
int lastl=root,lastr=root;
for(i=1;i<=m;i++)
{
PathXor(lastl,L[i].u),PathXor(lastr,L[i].v);
lastl=L[i].u,lastr=L[i].v;
int F=LCA(lastl,lastr);
NodeXor(F);
L[i].ans=ans+((Cnt[L[i].a]&&Cnt[L[i].b]&&L[i].b!=L[i].a)?-1:0);
NodeXor(F);
}
sort(L+1,L+1+m,cmp);
for(i=1;i<=m;i++)
printf("%d\n",L[i].ans);
return 0;
}