题意:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
题解:
动态书树上带修改查询
#include <bits/stdc++.h>
#define FOR(i,s,t) for(int i=(s);i<=(t);i++)
#define ROF(i,s,t) for(int i=(s);i>=(t);i--)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define fi first
#define se second
#define endl '\n'
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const ll mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int readInt(){
int x=0;
bool sign=false;
char c=getchar();
while(!isdigit(c)){
sign=c=='-';
c=getchar();
}
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return sign?-x:x;
}
ll readLong(){
ll x=0;
bool sign=false;
char c=getchar();
while(!isdigit(c)){
sign=c=='-';
c=getchar();
}
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return sign?-x:x;
}
string readString(){
string s;
char c=getchar();
while(isspace(c)){
c=getchar();
}
while(!isspace(c)){
s+=c;
c=getchar();
}
return s;
}
const int MAXN=1e5+10;
struct node{
int v,upv,downv,sum,lz;
bool lz_rev;
node *p,*s[2];
void build(int x)
{
v=upv=downv=x;
sum=1;
lz=0;
lz_rev=0;
p=s[0]=s[1]=NULL;
}
}*root[MAXN];
void update(node *now)
{
if(!now) return;
now->upv=now->s[0]?now->s[0]->upv:now->v;
now->downv=now->s[1]?now->s[1]->downv:now->v;
now->sum=1;
if(now->s[0]) now->sum+=now->s[0]->sum-(now->v==now->s[0]->downv);
if(now->s[1]) now->sum+=now->s[1]->sum-(now->v==now->s[1]->upv);
}
void print(node *now,int x)
{
if(!now) return;
now->v=now->upv=now->downv=x;
now->sum=1;
now->lz=x;
}
void rev(node *now)
{
if(now)
{
swap(now->s[0],now->s[1]);
swap(now->upv,now->downv);
now->lz_rev^=1;
}
}
void down(node *now)
{
if(now->lz_rev)
{
rev(now->s[0]);
rev(now->s[1]);
now->lz_rev=0;
}
if(now->lz)
{
print(now->s[0],now->lz);
print(now->s[1],now->lz);
now->lz=0;
}
update(now);
}
void link(node *f,node *x,bool d)
{
f->s[d]=x;
if(x) x->p=f;
update(f);
}
bool is_root(node *now){return !now->p||now!=now->p->s[0]&&now!=now->p->s[1];}
void rotate(node *now,bool d)
{
node *x=now->s[d],*p=now->p;
bool flag=is_root(now);
link(now,x->s[d^1],d);
link(x,now,d^1);
if(flag) x->p=p;
else link(p,x,now==p->s[1]);
}
stack<node*>s;
void splay(node *now)
{
s.push(now);
for(node *i=now;!is_root(i);i=i->p) s.push(i->p);
while(!s.empty()) down(s.top()),s.pop();
while(!is_root(now))
{
node *cur=now->p;
bool d1=now==cur->s[1];
if(is_root(cur))
{
rotate(cur,d1);
return;
}
node *x=cur->p;
bool d2=cur==x->s[1];
if(d1^d2) rotate(cur,d1),rotate(x,d2);
else rotate(x,d2),rotate(cur,d1);
}
}
void access(node *now)
{
node *x=NULL,*st=now;
while(now)
{
splay(now);
link(now,x,1);
x=now;
now=now->p;
}
splay(st);
}
void set_root(node *now){access(now),rev(now);}
void extract(node *x,node *y){set_root(x),access(y);}
void con(node *x,node *y){set_root(x),x->p=y;}
int n,m;
int main()
{
//freopen("2.in", "r", stdin);
//freopen("out.txt","w",stdout);
//ios::sync_with_stdio(0);
//cin>>n>>m;
n = readInt();
m = readInt();
for(int i=1;i<=n;++i)
{
int a = readInt();
root[i]=new node;
root[i]->build(a);
}
for(int i=1;i<n;++i)
{
int a = readInt(), b= readInt();
con(root[a],root[b]);
}
while(m--)
{
char op=getchar();
while(isspace(op)){
op=getchar();
}
int x,y,z;
if(op=='C')
{
x = readInt();
y = readInt();
z = readInt();
extract(root[x],root[y]);
print(root[y],z);
}
else
{
x = readInt();
y = readInt();
extract(root[x],root[y]);
printf("%d\n",root[y]->sum);
}
}
//
return 0;
}