用题解和讨论里的数据生成器对拍没找到错误
(用分块写的
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<cstring>
#include<bitset>
#define inf 0x7f7f7f7f
#define X 20005
#define ll long long
#define MOD 998244353
#define maxn 100050
using namespace std;
inline int Max(int a,int b) {return a>b?a:b;}
inline int Min(int a,int b) {return a<b?a:b;}
inline void Swap(int &a,int &b) {a=a^b;b=a^b;a=a^b;}
inline int scan()
{
register int x=0,f=0;
register char c=getchar();
while(c<'0') f|=(c=='-'),c=getchar();
while(c>='0') x=(x<<1)+(x<<3)+(c&15),c=getchar();
return f?-x:x;
}
inline void print(int x)
{
if(x/10) print(x/10);
putchar(x%10+48);
}
int edge_w[210000],edge_Next[210000],edge_to[210000];
int head[100005],total;
inline void add_edge(int u,int v)
{
edge_to[++total]=v;
edge_Next[total]=head[u];
head[u]=total;
}
int size[100005],son[100005],top[100005],father[100005],deep[100005];
void dfs_first(int s,int fa)
{
size[s]=1;
father[s]=fa;
deep[s]=deep[fa]+1;
for (register int e=head[s],Next;e;e=edge_Next[e])
{
Next=edge_to[e];
Next!=fa?(dfs_first(Next,s),size[s]+=size[Next],(size[Next]>size[son[s]]?son[s]=Next:0)):0;
}
return ;
}
int pointnum[100005],tree_to_line[100005],line_to_tree[100005],idcnt;
void dfs_second(int s,int Top)
{
idcnt++;
line_to_tree[idcnt]=s;
tree_to_line[s]=idcnt;
top[s]=Top;
if (son[s]) dfs_second(son[s],Top);
register int Next;
for (register int e=head[s];e;e=edge_Next[e])
{
Next=edge_to[e];
(Next!=father[s]&&Next!=son[s])?dfs_second(Next,Next),0:0;
}
return ;
}
set<int>check;
int n,m,q,k,x,y,s,p;
int block;
int left[5000],right[5000],pos[100005];
int sumblock[5000],date[100005],tag[5000];
inline void build()
{
block=sqrt(n);
for (int i=1;i<=block;i++)
{
tag[i]=inf;
left[i]=(i-1)*block+1;
right[i]=block*i;
}
right[block]=n;
for (int i=1;i<=n;i++)
date[i]=pointnum[line_to_tree[i]];
for (int i=1;i<=block;i++)
{
check.clear();
for (int j=left[i];j<=right[i];j++)
{
check.insert(date[j]);
pos[j]=i;
}
sumblock[i]=check.size();
}
}
inline void change(int l,int r,int cag)
{
for (int i=pos[l];i<=pos[r];i++)
{
if (l<=left[i]&&right[i]<=r)
{
tag[i]=cag;
date[left[i]]=cag;
date[right[i]]=cag;
sumblock[i]=1;
}
else
{
if (tag[i]!=inf)
{
for (int j=left[i];j<=right[i];j++)
date[j]=tag[i];
for (int j=Max(left[i],l);j<=Min(right[i],r);j++)
date[j]=cag;
if (cag==tag[i]) sumblock[i]=1;
else sumblock[i]=2;
tag[i]=inf;
continue;
}
check.clear();
for (int j=Max(left[i],l);j<=Min(right[i],r);j++)
date[j]=cag;
for (int j=left[i];j<=right[i];j++)
check.insert(date[j]);
sumblock[i]=check.size();
}
}
}
int lcolor,rcolor;
inline int query(int l,int r)
{
int res=0,sid=pos[l],eid=pos[r];
if (sid==eid)
{
if (tag[sid]!=inf) return 1;
check.clear();
for (int i=l;i<=r;i++)
check.insert(date[i]);
res=check.size();
return res;
}
if (tag[sid]!=inf) res=1;
else
{
check.clear();
for (int i=l;i<=right[sid];i++)
check.insert(date[i]);
res+=check.size();
}
for (int i=sid+1;i<eid;i++)
{
res+=sumblock[i];
if (date[left[i]-1]==date[left[i]]) res--;
}
if (tag[eid]!=inf)
for (int i=left[eid];i<=right[eid];i++)
date[i]=tag[eid];
if (right[eid]==r)
{
res+=sumblock[eid];
if (date[left[eid]-1]==date[left[eid]]) res--;
return res;
}
check.clear();
for (int i=left[eid];i<=r;i++)
check.insert(date[i]);
res+=check.size();
if (date[left[eid]-1]==date[left[eid]]) res--;
return res;
}
inline int checktopcolor(int x)
{
int belong=pos[tree_to_line[x]];
if (tag[belong]!=inf) return tag[belong];
return date[tree_to_line[x]];
}
inline void change_xtoy(int x,int y,int cag)
{
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) Swap(x,y);
change(tree_to_line[top[x]],tree_to_line[x],cag);
x=father[top[x]];
}
if (tree_to_line[x]>tree_to_line[y]) Swap(x,y);
change(tree_to_line[x],tree_to_line[y],cag);
return ;
}
inline int query_x_to_y(int x,int y)
{
int ans=0;
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) Swap(x,y);
ans+=query(tree_to_line[top[x]],tree_to_line[x]);
if (checktopcolor(top[x])==checktopcolor(father[top[x]])) ans--;
x=father[top[x]];
}
if (tree_to_line[x]>tree_to_line[y]) Swap(x,y);
ans+=query(tree_to_line[x],tree_to_line[y]);
return ans;
}
int cag;
int main()
{
n=scan();m=scan();s=1;
for (int i=1;i<=n;i++) pointnum[i]=scan();
for (int i=1;i<n;i++)
{
x=scan();y=scan();
add_edge(x,y);
add_edge(y,x);
}
dfs_first(s,0);
dfs_second(s,s);
build();
char order;
while (m--)
{
order=getchar();
while (order!='C'&&order!='Q') order=getchar();
if (order=='C')
{
x=scan();y=scan();cag=scan();
change_xtoy(x,y,cag);
}
else
{
x=scan();y=scan();
print(query_x_to_y(x,y));
putchar('\n');
}
}
return 0;
}