题目链接:传送门
题目大意:
给定一棵
n
n
n个节点的树,每个节点有一个颜色
a
i
a_i
ai。
有
m
m
m个询问,每次给出
u
,
v
,
a
,
b
u,v,a,b
u,v,a,b,表示
u
u
u到
v
v
v的路径上,把所有颜色
a
a
a看成颜色
b
b
b,求出有多少种颜色。
询问不会修改节点真实的颜色。
n
<
=
50000.
n<=50000.
n<=50000.
如果这是一个序列,那么显然是一个无修改莫队就解决了qwq。
然后把询问放在树上,就在树上进行莫队就吼了。
树上莫队方法参考:蒟蒻的题解qwq
然后把所有颜色
a
a
a看成
b
b
b,就判断一下:如果
a
a
a和
b
b
b都出现了,那么答案要-1(比较水qwq)。
毒瘤代码
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#define re register int
#define rl register ll
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
inline char GetChar() {
char ch=getchar();
while(ch!='Q' && ch!='R') ch=getchar();
return ch;
}
namespace I_Love {
const int Size=100005;
const int LOG=17;
int maxn,n,m,cnt,a[Size],head[Size],belong[Size];
struct Edge {
int v,next;
} w[Size<<1];
void AddEdge(int u,int v) {
w[++cnt].v=v;
w[cnt].next=head[u];
head[u]=cnt;
}
int tim,L[Size],R[Size],order[Size<<1];
int deep[Size],anc[Size][LOG];
void dfs(int x,int fa) {
order[L[x]=++tim]=x;
anc[x][0]=fa;
deep[x]=deep[fa]+1;
for(re i=1; i<=maxn; i++) {
anc[x][i]=anc[anc[x][i-1]][i-1];
}
for(int i=head[x]; i; i=w[i].next) {
int nxt=w[i].v;
if(nxt!=fa) {
dfs(nxt,x);
}
}
order[R[x]=++tim]=x;
}
int LCA(int u,int v) {
if(deep[u]<deep[v]) swap(u,v);
for(re i=maxn; i>=0; i--) {
if(deep[anc[u][i]]>=deep[v]) {
u=anc[u][i];
}
}
if(u==v) return u;
for(re i=maxn; i>=0; i--) {
if(anc[u][i]!=anc[v][i]) {
u=anc[u][i];
v=anc[v][i];
}
}
return anc[u][0];
}
int ans,vis[Size<<1],out[Size<<1];
bool flag[Size<<1];
inline void upd(int x) {
flag[x]=!flag[x];
if(flag[x]) {
if(!vis[a[x]]++) ans++;
} else {
if(!--vis[a[x]]) ans--;
}
}
struct apple {
int id,l,r,a,b,lca;
} Q[Size];
inline bool comp(apple x,apple y) {
if(belong[x.l]!=belong[y.l]) return belong[x.l]<belong[y.l];
return x.r<y.r;
}
void Fujibayashi_Ryou() {
n=read();
m=read();
int root=0;
int siz=sqrt(n);
maxn=log2(n)+1;
for(re i=1; i<=n; i++) {
a[i]=read();
belong[i]=(i-1)/siz+1;
}
for(re i=1; i<=n; i++) {
int u=read();
int v=read();
if(!u || !v) {
root=u|v;
} else {
AddEdge(u,v);
AddEdge(v,u);
}
}
dfs(root,0);
for(re i=1; i<=m; i++) {
Q[i].id=i;
Q[i].l=read();
Q[i].r=read();
Q[i].a=read();
Q[i].b=read();
Q[i].lca=LCA(Q[i].l,Q[i].r);
if(L[Q[i].l]>L[Q[i].r]) swap(Q[i].l,Q[i].r);
if(Q[i].l==Q[i].lca) {
Q[i].lca=0;
Q[i].l=L[Q[i].l];
Q[i].r=L[Q[i].r];
} else {
Q[i].l=R[Q[i].l];
Q[i].r=L[Q[i].r];
}
}
sort(Q+1,Q+1+m,comp);
int l=1,r=0;
for(re i=1; i<=m; i++) {
while(r<Q[i].r) upd(order[++r]);
while(r>Q[i].r) upd(order[r--]);
while(l<Q[i].l) upd(order[l++]);
while(l>Q[i].l) upd(order[--l]);
if(Q[i].lca) upd(Q[i].lca);
if(Q[i].a!=Q[i].b && vis[Q[i].a] && vis[Q[i].b]) {
out[Q[i].id]=ans-1;
} else {
out[Q[i].id]=ans;
}
if(Q[i].lca) upd(Q[i].lca);
}
for(re i=1; i<=m; i++) {
printf("%d\n",out[i]);
}
}
}
int main() {
I_Love::Fujibayashi_Ryou();
return 0;
}