题目描述
输入输出格式
输入格式:
输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
输入样例#1:
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
输出样例#1:
3
1
2
说明
Solution
太久没打过树剖了哈,代码能力弱的一批...
这道题需要进行改进的地方是线段树部分.
我们新维护两个变量:
[ll[node],rr[node]
]
分别用于储存当前线段树节点的左端颜色和右端颜色.
以在查询时达到判重的作用.
修改时也只需要注意下这两个变量即可.
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=100008;
struct sj{int to,next;}a[maxn*2];
int x,y,z,dep[maxn],fa[maxn];
int n,m,col[maxn],c[maxn],num;
int head[maxn],size,id[maxn],fuck[maxn];
int siz[maxn],zu[maxn],son[maxn];
int ll[maxn*4],rr[maxn*4],sgm[maxn*4],lazy[maxn*4];
void add(int x,int y)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
}
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(!siz[tt])
{
dep[tt]=dep[x]+1;
fa[tt]=x;
dfs1(tt);
siz[x]+=siz[tt];
if(siz[tt]>siz[son[x]])
son[x]=tt;
}
}
}
void dfs2(int x,int anc)
{
zu[x]=anc; c[++num]=col[x]; id[x]=num;
if(son[x]) dfs2(son[x],anc);
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(!zu[tt])
if(tt==son[x])
continue;
else dfs2(tt,tt);
}
}
void push_down(int node)
{
ll[node*2]=lazy[node]; rr[node*2]=lazy[node];
ll[node*2+1]=lazy[node]; rr[node*2+1]=lazy[node];
sgm[node*2]=1; sgm[node*2+1]=1;
lazy[node*2]=lazy[node]; lazy[node*2+1]=lazy[node];
lazy[node]=0;
}
void update(int node)
{
ll[node]=ll[node*2]; rr[node]=rr[node*2+1];
sgm[node]=sgm[node*2]+sgm[node*2+1];
if(rr[node*2]==ll[node*2+1]) sgm[node]--;
}
void build(int node,int l,int r)
{
if(l==r)
{
ll[node]=c[l];
rr[node]=c[r];
sgm[node]=1;
return;
}
int mid=(l+r)/2;
build(node*2,l,mid);
build(node*2+1,mid+1,r);
update(node);
return;
}
void change(int node,int l,int r,int L,int R,int cc)
{
if(l>R||L>r)return;
if(l>=L&&r<=R)
{
lazy[node]=cc;
ll[node]=lazy[node];
rr[node]=lazy[node];
sgm[node]=1;
return;
}
if(lazy[node]!=0)
push_down(node);
int mid=(l+r)/2;
change(node*2,l,mid,L,R,cc);
change(node*2+1,mid+1,r,L,R,cc);
update(node);
}
int query(int node,int l,int r,int L,int R)
{
if(l>R||L>r)return 0;
if(l>=L&&r<=R){
return sgm[node];}
if(lazy[node]!=0)
push_down(node);
int mid=(l+r)/2;
int lll=query(node*2,l,mid,L,R);
int rrr=query(node*2+1,mid+1,r,L,R);
int ans=lll+rrr;
if(rr[node*2]==ll[node*2+1]&&(lll!=0&&rrr!=0))return ans-1;
return ans;
}
void kuai(int x,int y,int z)
{
while(zu[x]!=zu[y])
{
if(dep[zu[x]]<dep[zu[y]])
swap(x,y);
change(1,1,n,id[zu[x]],id[x],z);
x=fa[zu[x]];
}
if(dep[x]>dep[y])swap(x,y);
change(1,1,n,id[x],id[y],z);
}
int newww(int r,int z,int y,int p)
{
if (z==y) return ll[r];
if (lazy[r]) push_down(r);
int k=(z+y)/2;
if (p>k) return newww(r*2+1,k+1,y,p);
else return newww(r*2,z,k,p);
}
int check(int x,int y)
{
int kk=0,nx,ny;
while (zu[x]!=zu[y])
{
if (dep[zu[x]]>dep[zu[y]])
swap(x,y);
kk+=query(1,1,n,id[zu[y]],id[y]);
nx=newww(1,1,n,id[zu[y]]);
ny=newww(1,1,n,id[fa[zu[y]]]);
y=fa[zu[y]];
if (nx==ny) kk--;
}
if (dep[x]>dep[y]) swap(x,y);
kk+=query(1,1,n,id[x],id[y]);
cout<<(kk?kk:1)<<endl;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&col[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs1(1);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
char ch; cin>>ch;
if(ch=='Q')
scanf("%d%d",&x,&y),
check(x,y);
else
scanf("%d%d%d",&x,&y,&z),
kuai(x,y,z);
}
}