一个比较裸的树剖题
先考虑区间处理的情况,我们维护区间颜色段数,区间左右端点的颜色之后这就可以满足区间合并了
然后用树剖的方法处理一下就好
ps:用结构体保存区间值重载加号表示区间合并不能更方便
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 312345;
struct Info{
int l,r;
int siz;
void init(int x){
l = r = x;
siz = 1;
}
void clear(){
l = r = siz = -1;
}
Info(){}
Info(int l,int r,int siz):l(l),r(r),siz(siz){}
};
Info rev(Info v){
return Info(v.r,v.l,v.siz);
}
Info operator + (Info l,Info r){
if(l.siz == -1) return r;
if(r.siz == -1) return l;
Info ret(l.l,r.r,l.siz+r.siz);
if(l.r == r.l)
ret.siz--;
return ret;
}
Info info[maxn*4];
int lazy[maxn*4];
#define root 1,1,n
#define Now int o,int l,int r
#define Mid int m = l + (r - l)/2
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
void push_down(Now){
int v = lazy[o];
lazy[o] = -1;
if(l != r){
info[o<<1].init(v);
info[o<<1|1].init(v);
lazy[o<<1] = lazy[o<<1|1] = v;
}
}
void update(Now,int ul,int ur,int v){
if(ul <= l && r <= ur){
lazy[o] = v;
info[o].init(v);
return;
}
Mid;
if(lazy[o] != -1)push_down(o,l,r);
if(ul <= m) update(lson,ul,ur,v);
if(m+1 <= ur) update(rson,ul,ur,v);
info[o] = info[o<<1] + info[o<<1|1];
}
Info query(Now,int ql,int qr){
if(ql <= l && r <= qr)
return info[o];
Mid;
if(lazy[o] != -1)
push_down(o,l,r);
Info ret;
ret.clear();
if(ql <= m) ret = query(lson,ql,qr) + ret;
if(m+1 <= qr) ret = ret + query(rson,ql,qr);
return ret;
}
void sinit(){
memset(lazy,-1,sizeof(lazy));
}
//---treesplite
vector<int> edge[maxn];
void Link(int st,int ed){
edge[st].push_back(ed);
edge[ed].push_back(st);
}
void init(int n){
for(int i=0;i<=n;i++){
edge[i].clear();
}
}
int fa[maxn],son[maxn],siz[maxn];
int deep[maxn],top[maxn],tid[maxn];
int _cnt;
void dffs(int st,int Fa,int Deep){
son[st] = -1,fa[st] = Fa;
deep[st] = Deep,siz[st] = 1;
for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){
int x = *it;
if( x != Fa){
dffs(x,st,Deep+1);
siz[st] += siz[x];
if(son[st] == -1 || siz[son[st]] < siz[x])
son[st] = x;
}
}
}
void dfss(int st,int Top){
tid[st] = _cnt ++;
top[st] = Top;
if(son[st] != -1){
dfss(son[st],Top);
}
for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){
int x = *it;
if(x != fa[st] && x != son[st]){
dfss(x,x);
}
}
}
void splite(){
_cnt = 1;
dffs(1,-1,1);
dfss(1,1);
}
int n;
void UPD(int x,int y,int v){
int tx,ty;
tx = top[x],ty = top[y];
while(tx != ty){
if(deep[tx] < deep[ty]){
swap(x,y),swap(tx,ty);
}
update(root,tid[tx],tid[x],v);
x = fa[tx],tx = top[x];
}
if(deep[x] < deep[y])
swap(x,y);
update(root,tid[y],tid[x],v);
}
Info QUE(int x,int y){
Info X,Y;
X.clear();
Y.clear();
int tx,ty;
tx = top[x],ty = top[y];
while(tx != ty){
if(deep[tx] < deep[ty])
swap(x,y),swap(X,Y),swap(tx,ty);
X = query(root,tid[tx],tid[x]) + X;
x = fa[tx],tx = top[x];
}
if(deep[x] < deep[y])
swap(x,y),swap(X,Y);
return rev(X) + rev(query(root,tid[y],tid[x])) + Y;
}
int arr[maxn];
int main(){
int m;
while(~scanf("%d %d",&n,&m)){
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
init(n);
int x,y;
for(int i=1;i<n;i++){
scanf("%d %d",&x,&y);
Link(x,y);
}
splite();
sinit();
for(int i=1;i<=n;i++){
update(root,tid[i],tid[i],arr[i]);
}
int v;
char ord[3];
while(m--){
scanf("%s",ord);
scanf("%d %d",&x,&y);
if(*ord == 'Q'){
printf("%d\n",QUE(x,y).siz);
}
else{
scanf("%d",&v);
UPD(x,y,v);
}
}
}
return 0;
}
初始化的时候把lazy memset成0的丝薄应该只有我
还有树剖查询的时候忘记加上原来的区间直接赋值的也是没谁了。。。