题意:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ 112221 ” 由3段组成:11 、222 和1 。
区间更新,区间查询。
很容易写错,开始cnt忘记清零找了一小时。r不小心写成l又找半小时。。。
一定要细心,这种题出错很难找。
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
#define maxn 300000
int n,m,dep[maxn],top[maxn],size[maxn],son[maxn],fa[maxn],id[maxn],val[maxn],val_pre[maxn];
struct node{
int u,v,next;
}e[maxn];
int head[maxn],topw,q,num;
void addedge(int x,int y)
{
e[num].u=x;e[num].v=y;e[num].next=head[x];head[x]=num++;
}
void dfs_1(int u,int f,int d)
{
size[u]=1;
dep[u]=d;
fa[u]=f;
son[u]=0;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==f) continue;
dfs_1(v,u,d+1);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
void dfs_2(int u,int tp)
{
top[u]=tp;
id[u]=++topw;
if(son[u]) dfs_2(son[u],tp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==son[u]||v==fa[u]) continue;
dfs_2(v,v);
}
}
struct Tree{
int l,r,lc,rc,cnt,lazy;
Tree()
{
cnt=0;
}
}tree[maxn];
void push_up(int rt)
{
tree[rt].cnt=tree[rt<<1].cnt+tree[rt<<1|1].cnt;
if(tree[rt<<1].rc==tree[rt<<1|1].lc) tree[rt].cnt--;
tree[rt].lc=tree[rt<<1].lc;tree[rt].rc=tree[rt<<1|1].rc;
}
void push_down(int rt)
{
if(tree[rt].lazy!=-1)
{
tree[rt<<1].lazy=tree[rt<<1].lc=tree[rt<<1].rc=tree[rt].lazy;tree[rt<<1].cnt=1;
tree[rt<<1|1].lazy=tree[rt<<1|1].lc=tree[rt<<1|1].rc=tree[rt].lazy;tree[rt<<1|1].cnt=1;
tree[rt].lazy=-1;
}
}
void build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].lazy=-1;
if(l==r)
{
tree[rt].cnt=1;tree[rt].lc=tree[rt].rc=val[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
push_up(rt);
}
void adde(int l,int r,int val,int rt)
{
if(tree[rt].l>=l&&tree[rt].r<=r)
{
tree[rt].cnt=1;
tree[rt].lazy=tree[rt].lc=tree[rt].rc=val;
return ;
}
push_down(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
if(l<=mid) adde(l,r,val,rt<<1);
if(r>mid) adde(l,r,val,rt<<1|1);
push_up(rt);
}
void gao1(int u,int v,int val)
{
int tp1=top[u],tp2=top[v];
while(tp1!=tp2)
{
if(dep[tp1]<dep[tp2])
{
swap(tp1,tp2);
swap(u,v);
}
adde(id[tp1],id[u],val,1);
u=fa[tp1];
tp1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
adde(id[u],id[v],val,1);
}
Tree merge(Tree a,Tree b)
{
Tree ans;
if(a.cnt==0) return b;
if(b.cnt==0) return a;
ans.lc=a.lc;
ans.rc=b.rc;
ans.cnt=a.cnt+b.cnt;
if(a.rc==b.lc) ans.cnt--;
return ans;
}
Tree query(int l,int r,int rt)
{
if(tree[rt].l>=l&&tree[rt].r<=r) return tree[rt];
push_down(rt);
Tree ans;
int mid=(tree[rt].l+tree[rt].r)>>1;
if(l<=mid) ans=merge(query(l,r,rt<<1),ans);
if(r>mid) ans=merge(ans,query(l,r,rt<<1|1));
push_up(rt);
return ans;
}
int change(int u,int v)
{
Tree ans1,ans2;
int tp1=top[u],tp2=top[v];
while(tp1!=tp2)
{
if(dep[tp1]<dep[tp2])
{
swap(ans1,ans2);swap(u,v);swap(tp1,tp2);
}
ans1=merge(query(id[tp1],id[u],1),ans1);
u=fa[tp1];tp1=top[u];
}
if(dep[u]>dep[v])
{
swap(u,v);swap(ans1,ans2);
}
ans2=merge(query(id[u],id[v],1),ans2);
if(ans1.cnt==0) return ans2.cnt;
if(ans2.cnt==0) return ans1.cnt;
int ans=ans1.cnt+ans2.cnt;
if(ans1.lc==ans2.lc) ans--;
return ans;
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
memset(head,-1,sizeof(head));
topw=0;num=0;
for(int i=1;i<=n;i++)scanf("%d",&val_pre[i]);
for(int i=1;i<n;i++)
{
int x,y;scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs_1(1,0,1);
dfs_2(1,1);
for(int i=1;i<=n;i++)
{
val[id[i]]=val_pre[i];
}
build(1,topw,1);
//for(int i=1;i<=n;i++) printf("%d\n",tree[i].cnt);
while(q--)
{
char s[10];
scanf("%s",s);
if(s[0]=='Q')
{
int x,y;scanf("%d%d",&x,&y);
printf("%d\n",change(x,y));
}
else
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
gao1(x,y,z);
}
}
}
return 0;
}