BZOJ 2243染色木鎖断分
木を与えて、木の上の各点は1つの色があります
2つのアクションを指定
Q:問い合わせノードxからノードyへのパス上の色セグメント数(連続して同じ色が同じセグメントとみなされる)、例えば「112212」は、「11」、「222」、「1」の3セグメントからなる.
C:ノードxからノードyパス上の全ての点を色zに染める
まずこの問題は一見して木の鎖の断分であることがわかる.
そして線分ツリーの区間マージの問題です
各ノードは、区間内のカラーセグメント数、左端のカラー、右端のカラーを保存します.
2区間を併合する場合、左区間右端点と右区間左端点の色が同じであれば、新区間段数は左右区間の和-1となる
そうでなければ両区間の和となる
質問するときもその対処法ですが、左右が逆にならないように気をつけてください
もともとすぐに书き终わってからCとQを読み込んだ时Linuxの中の帰りを忘れてしまったのは'r'これくらいP事WAだったので午后三千组のデータを撮って全部渡して最初の点でWA私を絞めて行きました...
とにかくコードを貼る
2つのアクションを指定
Q:問い合わせノードxからノードyへのパス上の色セグメント数(連続して同じ色が同じセグメントとみなされる)、例えば「112212」は、「11」、「222」、「1」の3セグメントからなる.
C:ノードxからノードyパス上の全ての点を色zに染める
まずこの問題は一見して木の鎖の断分であることがわかる.
そして線分ツリーの区間マージの問題です
各ノードは、区間内のカラーセグメント数、左端のカラー、右端のカラーを保存します.
2区間を併合する場合、左区間右端点と右区間左端点の色が同じであれば、新区間段数は左右区間の和-1となる
そうでなければ両区間の和となる
質問するときもその対処法ですが、左右が逆にならないように気をつけてください
もともとすぐに书き终わってからCとQを読み込んだ时Linuxの中の帰りを忘れてしまったのは'r'これくらいP事WAだったので午后三千组のデータを撮って全部渡して最初の点でWA私を絞めて行きました...
とにかくコードを貼る
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ls tree[p].lson
#define rs tree[p].rson
#define M 100100
using namespace std;
struct Col{ int num,lcol,rcol; }empty;
struct Tree{
Col col,mark;
int lson,rson;
}tree[M<<1];
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot=1;
int n,m,fa[M],col[M],son[M],dpt[M],siz[M],pos[M],top[M],poscol[M],cnt;
void add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void dfs1(int x)
{
int i;
siz[x]=1;
dpt[x]=dpt[fa[x]]+1;
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x])
continue;
fa[table[i].to]=x;
dfs1(table[i].to);
if(siz[table[i].to]>siz[son[x]])
son[x]=table[i].to;
siz[x]+=siz[table[i].to];
}
}
void dfs2(int x)
{
int i;
if(son[fa[x]]==x)
top[x]=top[fa[x]];
else
{
top[x]=x;
for(i=x;i;i=son[i])
pos[i]=++cnt;
}
poscol[pos[x]]=col[x];
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x])
continue;
dfs2(table[i].to);
}
}
Col operator + (Col x,Col y)
{
Col re;
re.lcol=x.lcol;
re.rcol=y.rcol;
re.num=x.num+y.num-(x.rcol==y.lcol);
return re;
}
void Build_tree(int p,int x,int y)
{
int mid=x+y>>1;
if(x==y)
{
tree[p].col.num=1;
tree[p].col.lcol=tree[p].col.rcol=poscol[mid];
return ;
}
ls=++tot;rs=++tot;
Build_tree(ls,x,mid);
Build_tree(rs,mid+1,y);
tree[p].col=tree[ls].col+tree[rs].col;
}
Col getans(int p,int x,int y,int l,int r)
{
int mid=x+y>>1;
if(x==l&&y==r)
return tree[p].col;
if(tree[p].mark.num)
{
tree[ls].col=tree[rs].col=tree[p].mark;
tree[ls].mark=tree[rs].mark=tree[p].mark;
tree[p].mark=empty;
}
if(r<=mid) return getans(ls,x,mid,l,r);
if(l>mid) return getans(rs,mid+1,y,l,r);
return getans(ls,x,mid,l,mid) + getans(rs,mid+1,y,mid+1,r);
}
int Q(int x,int y)
{
Col xcol=empty,ycol=empty;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dpt[fx]<dpt[fy])
swap(x,y),swap(fx,fy),swap(xcol,ycol);
xcol=getans(0,1,n,pos[fx],pos[x])+xcol;
x=fa[fx];
fx=top[x];
}
if(dpt[x]<dpt[y])
swap(x,y),swap(fx,fy),swap(xcol,ycol);
xcol=getans(0,1,n,pos[y],pos[x])+xcol;
return xcol.num+ycol.num-(xcol.lcol==ycol.lcol);
}
void change(int p,int x,int y,int l,int r,Col z)
{
int mid=x+y>>1;
if(x==l&&y==r)
{
tree[p].col=z;
tree[p].mark=z;
return ;
}
if(tree[p].mark.num)
{
tree[ls].col=tree[rs].col=tree[p].mark;
tree[ls].mark=tree[rs].mark=tree[p].mark;
tree[p].mark=empty;
}
if(r<=mid) change(ls,x,mid,l,r,z);
else if(l>mid) change(rs,mid+1,y,l,r,z);
else change(ls,x,mid,l,mid,z) , change(rs,mid+1,y,mid+1,r,z);
tree[p].col=tree[ls].col+tree[rs].col;
}
void C(int x,int y,int z)
{
int fx=top[x],fy=top[y];
Col zmark;
zmark.num=1;
zmark.lcol=zmark.rcol=z;
while(fx!=fy)
{
if(dpt[fx]<dpt[fy])
swap(x,y),swap(fx,fy);
change(0,1,n,pos[fx],pos[x],zmark);
x=fa[fx];
fx=top[x];
}
if(dpt[x]<dpt[y])
swap(x,y),swap(fx,fy);
change(0,1,n,pos[y],pos[x],zmark);
}
inline char get_char()
{
char c;
do c=getchar(); while(c=='
'||c==' '||c=='\r');
return c;
}
int main()
{
int i,x,y,z;
char p;
cin>>n>>m;
for(i=1;i<=n;i++)
scanf("%d",&col[i]),col[i]++;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
tot=0;
dfs1(1);
dfs2(1);
Build_tree(0,1,n);
for(i=1;i<=m;i++)
{
p=get_char();
if(p=='Q')
{
scanf("%d%d",&x,&y);
printf("%d
",Q(x,y));
}
else
{
scanf("%d%d%d",&x,&y,&z);
C(x,y,z+1);
}
}
}