2019.9.?Za

Good morning before the Za (I would say I did not save the attached twice kick led to heavy hit it twice

definition

Chain is to split the tree into the tree split over a series of chains and chain data structure into ⾏ maintain
normal light and heavy chains are split Remedies split, is the so-called light and heavy chains for the node u
with a Submenu node v, size [v], v is largest and the side edge of u heavy, the other side is a light side
where size [v] v is the number of nodes of the tree rooted submenus, composed entirely of the heavy side of
the path is re-route
according to the theory demonstrated on the file, the state does not exceed at any point to the root path ⼀ \ (logN \) strips
light side and \ (logN \) two heavy path

definition

Defined heavy child node represents the largest subtree its child nodes child nodes. If there is the same, taken at random. If no children, no.

Defined light child node represents the remaining child nodes.

From this node to the child node Bianjiao heavy weight side .

Telling them to other nodes leptons light side .

Some end-weight convergence of sides constituting the heavy chain .

To the single node as the heavy chain also, then the entire tree was split into a plurality of heavy chains.

This figure super clear

Construct

Dfs pass the first frame
is obtained for each node of the tree depth \ (DEP [X] \) , which is a small tree root Submenu zoomed \ (size [x] \)

第⼆遍dfs
以根节点为起点,向下拓展构建重链
选择最⼤的⼀个⼦树的根继承当前重链
其余节点,都以该节点为起点向下重新拉⼀条重链
给每个结点分配⼀个位置编号,每条重链就相当于⼀段区间,用
数据结构维护
把所有的重链首尾相接,放到同⼀个数据结构上,然后维护这⼀
个整体即可

void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        if((v=e[i].v)==fa) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>mxs) son[u]=v,mxs=sz[v];
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx;
    wt[idx]=a[u],top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt){
        if((v=e[i].v)==f[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

实战

luogu模板

如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

操作1: 格式:$ 1 x y z $ 表示将树从x到y结点最短路径上所有节点的值都加上z
操作2: 格式:$ 2 x y $表示求树从x到y结点最短路径上所有节点的值之和
操作3: 格式:\(3\ x\ z\) 表示将以x为根节点的子树内所有节点值都加上z
操作4: 格式:$ 4 x $表示求以x为根节点的子树内所有节点值之和

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define Abs(x) ((x)<0?-(x):(x))
#define ls (o<<1)
#define rs (o<<1|1)
const int N=1e5+10,M=1e5+50,inf=0x3f3f3f3f;
int n,m,rt,P,a[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot;
}
int idx=0,dfn[N],f[N],son[N],top[N],dep[N],sz[N],wt[N];
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        if((v=e[i].v)==fa) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>mxs) son[u]=v,mxs=sz[v];
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx;
    wt[idx]=a[u],top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt){
        if((v=e[i].v)==f[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}


struct node{int add,val;}t[N<<2];
void pup(int o){t[o].val=t[ls].val+t[rs].val;}
void updnode(int o,int l,int r,int k){
    t[o].val=(t[o].val+(r-l+1)*k)%P,t[o].add=(t[o].add+k)%P;
}
void pudw(int o,int l,int r){
    if(!t[o].add) return;
    int mid=l+r>>1;
    updnode(ls,l,mid,t[o].add),updnode(rs,mid+1,r,t[o].add);
    t[o].add=0;
}
void upd(int o,int l,int r,int x,int y,int k){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){updnode(o,l,r,k);return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    upd(ls,l,mid,x,y,k),upd(rs,mid+1,r,x,y,k);
    pup(o);
}
void build(int o,int l,int r){
    t[o].add=0;
    if(l==r){t[o].val=wt[l];return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pup(o);
}
int query(int  o,int l,int r,int x,int y){
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y) return t[o].val;
    pudw(o,l,r);
    int mid=l+r>>1,ans=0;
    ans=(ans+query(ls,l,mid,x,y))%P,ans=(ans+query(rs,mid+1,r,x,y))%P;
    pup(o);
    return ans;
}

void updrange(int x,int y,int k){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        upd(1,1,n,dfn[top[x]],dfn[x],k);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    upd(1,1,n,dfn[x],dfn[y],k);
}
int qrange(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);//不在同一条链上
        ans=(ans+query(1,1,n,dfn[top[x]],dfn[x]))%P;
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=(ans+query(1,1,n,dfn[x],dfn[y]))%P;
    return ans;
}

void updson(int x,int k){
    upd(1,1,n,dfn[x],dfn[x]+sz[x]-1,k);
}
int qson(int x){
    return query(1,1,n,dfn[x],dfn[x]+sz[x]-1);
}


int main(){
//  freopen("in.txt","r",stdin);
    //freopen("and.out","w",stdout);
    rd(n),rd(m),rd(rt),rd(P);
    for(int i=1;i<=n;++i) rd(a[i]);
    for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
    dfs1(rt,0),dfs2(rt,rt);
    build(1,1,n);
    for(int i=1,opt,x,y,k;i<=m;++i){
        rd(opt);
        if(opt==1) rd(x),rd(y),rd(k),updrange(x,y,k);
        else if(opt==2) rd(x),rd(y),printf("%d\n",qrange(x,y));
        else if(opt==3) rd(x),rd(k),updson(x,k);
        else if(opt==4) rd(x),printf("%d\n",qson(x));
    }
    return 0;
}

[HAOI2015]树上操作

P3178 [HAOI2015]树上操作 bzoj1036

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

  • 操作 1 :把某个节点 x 的点权增加 a 。
  • 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  • 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

==一个模板题

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ls (o<<1)
#define rs (o<<1|1)
const int N=1e5+10,M=1e5+50,inf=0x3f3f3f3f;
int n,m,rt,P;ll a[N],wt[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot;
}
int idx=0,dfn[N],f[N],son[N],top[N],dep[N],sz[N];
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        if((v=e[i].v)==fa) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>mxs) son[u]=v,mxs=sz[v];
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx;
    wt[idx]=a[u],top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt){
        if((v=e[i].v)==f[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}


struct node{ll add,val;}t[N<<2];
void pup(int o){t[o].val=t[ls].val+t[rs].val;}
void updnode(int o,int l,int r,ll k){
    t[o].val+=(ll)(r-l+1)*k,t[o].add+=k;
}
void pudw(int o,int l,int r){
    if(!t[o].add) return;
    int mid=l+r>>1;
    updnode(ls,l,mid,t[o].add),updnode(rs,mid+1,r,t[o].add);
    t[o].add=0;
}
void upd(int o,int l,int r,int x,int y,ll k){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){updnode(o,l,r,k);return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    upd(ls,l,mid,x,y,k),upd(rs,mid+1,r,x,y,k);
    pup(o);
}
void upd2(int o,int l,int r,int x,ll k){
    if(l==r){t[o].val+=k;return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    if(x<=mid) upd2(ls,l,mid,x,k);
    else upd2(rs,mid+1,r,x,k);
    pup(o);
}
void build(int o,int l,int r){
    t[o].add=0;
    if(l==r){t[o].val=wt[l];return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pup(o);
}
ll query(int  o,int l,int r,int x,int y){
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y) return t[o].val;
    pudw(o,l,r);
    int mid=l+r>>1;ll ans=0;
    ans+=query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    pup(o);
    return ans;
}

void updrange(int x,int y,ll k){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        upd(1,1,n,dfn[top[x]],dfn[x],k);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    upd(1,1,n,dfn[x],dfn[y],k);
}
ll qrange(int x,int y){
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);//不在同一条链上
        ans+=query(1,1,n,dfn[top[x]],dfn[x]);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=query(1,1,n,dfn[x],dfn[y]);
    return ans;
}

void updson(int x,ll k){
    upd(1,1,n,dfn[x],dfn[x]+sz[x]-1,k);
}
ll qson(int x){
    return query(1,1,n,dfn[x],dfn[x]+sz[x]-1);
}


int main(){
//  freopen("in.txt","r",stdin);
    //freopen("and.out","w",stdout);
    rd(n),rd(m),rt=1;
    for(int i=1;i<=n;++i) rd(a[i]);
    for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
    dfs1(rt,0),dfs2(rt,rt);
    build(1,1,n);
    int opt,x;ll k;
    for(int i=1;i<=m;++i){
        rd(opt),rd(x);
        if(opt==1) rd(k),upd2(1,1,n,dfn[x],k);
        else if(opt==2) rd(k),updson(x,k);
        else if(opt==3) printf("%lld\n",qrange(x,rt));
    }
    return 0;
}

[ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计 bzoj1036

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

注意:从点u到点v的路径上的节点包括u和v本身

还是模板==

以后还是少用点宏定义 ==这个好恐怖

宏定义Max上去是将里面的数复制了一遍 如果放的是函数 那就会跑两次!! 然后t到飞起

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define Abs(x) ((x)<0?-(x):(x))
#define ls (o<<1)
#define rs (o<<1|1)
const int N=30000+10,M=1e5+50,inf=0x3f3f3f3f;
int n,m,rt,P,a[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot;
}
int idx=0,dfn[N],sz[N],f[N],dep[N],son[N],top[N],wt[N];
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        if((v=e[i].v)==fa) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(mxs<sz[v]) mxs=sz[v],son[u]=v;
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx,wt[idx]=a[u],top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt)
        if((v=e[i].v)!=f[u]&&v!=son[u]) dfs2(v,v);
}

struct node{int sum,mx;}t[N<<2];
void pup(int o){
    t[o].sum=t[ls].sum+t[rs].sum;
    t[o].mx=Max(t[ls].mx,t[rs].mx);
}
void upd(int o,int l,int r,int x,int k){
    if(l==r){t[o].mx=t[o].sum=k;return;}
    int mid=l+r>>1;
    if(x<=mid) upd(ls,l,mid,x,k);
    else upd(rs,mid+1,r,x,k);
    pup(o);
}
void build(int o,int l,int r){
    if(l==r){t[o].mx=t[o].sum=wt[l];return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pup(o);
}
int qsum(int o,int l,int r,int x,int y){
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y) return t[o].sum;
    int mid=l+r>>1,ans=0;
    ans=qsum(ls,l,mid,x,y)+qsum(rs,mid+1,r,x,y);
    return ans;
}
int qmax(int o,int l,int r,int x,int y){
    if(l>y||r<x) return -inf;
    if(x<=l&&r<=y) return t[o].mx;
    int mid=l+r>>1,ans;
    ans=max(qmax(ls,l,mid,x,y),qmax(rs,mid+1,r,x,y));
    return ans;
}

int Qsum(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=qsum(1,1,n,dfn[top[x]],dfn[x]);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=qsum(1,1,n,dfn[x],dfn[y]);
    return ans;
}
int Qmax(int x,int y){
    int ans=-inf;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=max(ans,qmax(1,1,n,dfn[top[x]],dfn[x]));
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=max(ans,qmax(1,1,n,dfn[x],dfn[y]));
    return ans;
}

int main(){
//  freopen("in.txt","r",stdin);
    //freopen("and.out","w",stdout);
    rd(n),rt=1;
    for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
    for(int i=1;i<=n;++i) rd(a[i]);
    dfs1(rt,0),dfs2(rt,rt);
    build(1,1,n);
    rd(m);char opt[10];
    for(int i=1,x,y,k;i<=m;++i){
        scanf("%s",opt);rd(x),rd(y);
        if(opt[1]=='M') printf("%d\n",Qmax(x,y));
        else if(opt[1]=='S') printf("%d\n",Qsum(x,y));
        else upd(1,1,n,dfn[x],y);
    }
    return 0;
}

[NOI2015]软件包管理器]

P2146 [NOI2015]软件包管理器 bzoj4196

开始把题理解错了...

安装 查询从安装点到根节点有多少个未安装

卸载 查询以卸载点为根节点的子树有多少个安装了的

==还是一个模板

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define Abs(x) ((x)<0?-(x):(x))
#define ls (o<<1)
#define rs (o<<1|1)
const int N=1e5+10,M=1e5+50,inf=0x3f3f3f3f;
int n,m,rt,P,a[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int idx=0,dfn[N],sz[N],dep[N],son[N],f[N],top[N];
int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot;
}
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        dfs1((v=e[i].v),u);sz[u]+=sz[v];
        if(mxs<sz[v]) mxs=sz[v],son[u]=v;
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx,top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt)
    if((v=e[i].v)!=son[u]) dfs2(v,v);
}

int ans;
struct node{int tg,val;}t[N<<2];
void pup(int o){
    t[o].val=t[ls].val+t[rs].val;
}
void upd1(int o,int l,int r){
    t[o].tg=1,t[o].val=r-l+1;
}
void upd2(int o,int l,int r){
    t[o].tg=2,t[o].val=0;
}
void pudw(int o,int l,int r){
    //if(!t[o].tg) return;
    int mid=l+r>>1;
    if(t[o].tg==1) upd1(ls,l,mid),upd1(rs,mid+1,r);
    else if(t[o].tg==2) upd2(ls,l,mid),upd2(rs,mid+1,r);
    t[o].tg=0;
}
void install(int o,int l,int r,int x,int y){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){
        ans+=(r-l+1-t[o].val),upd1(o,l,r);
        return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    install(ls,l,mid,x,y),install(rs,mid+1,r,x,y);
    pup(o);
}
void uninstall(int o,int l,int r,int x,int y){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){ans+=t[o].val,upd2(o,l,r);return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    uninstall(ls,l,mid,x,y),uninstall(rs,mid+1,r,x,y);
    pup(o);
}

void work(int x,int typ){
    if(typ==1){
        while(top[x]!=rt){
            install(1,1,n,dfn[top[x]],dfn[x]);
            x=f[top[x]];
        }
        install(1,1,n,dfn[rt],dfn[x]);
    }
    else{
        uninstall(1,1,n,dfn[x],dfn[x]+sz[x]-1);
    }
    printf("%d\n",ans);
}

int main(){
//  freopen("in.txt","r",stdin);
    //freopen("and.out","w",stdout);
    rd(n),rt=0;
    for(int i=1,fa;i<n;++i) rd(fa),add(fa,i);
    dfs1(rt,rt),dfs2(rt,rt);
    rd(m);
    char opt[20];
    for(int i=1;i<=(n<<1);++i) t[i].tg=0;
    for(int i=1,x;i<=m;++i){
        scanf("%s",opt);rd(x);ans=0;
        if(opt[0]=='i') work(x,1);
        else work(x,2);
    }
    return 0;
}

[SDOI2011] 染色

P2486 [SDOI2011]染色 bzoj2243

一个上午都在搞它 注意一下询问时的操作

实在看不出来哪错了 一发重构 我A了... 题还是很好的

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
const int N=110000,MAX=110000;
#define ls (o<<1)
#define rs (o<<1|1)
using namespace std;
int n,m,a[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

struct node{int sum;int lc,rc,tg;}t[MAX<<2];
int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot;
}
int idx=0,dfn[N],f[N],son[N],top[N],dep[N],sz[N],wt[N];
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,f[u]=fa,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        if((v=e[i].v)==fa) continue;
        dfs1(v,u),sz[u]+=sz[v];
        if(sz[v]>mxs) son[u]=v,mxs=sz[v];
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx,wt[idx]=a[u],top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt)
        if((v=e[i].v)!=f[u]&&v!=son[u]) dfs2(v,v);
}


void pup(int o){
    t[o].sum=t[ls].sum+t[rs].sum;
    if(t[ls].rc==t[rs].lc)t[o].sum--;
    t[o].lc=t[ls].lc,t[o].rc=t[rs].rc;
}
void updnode(int o,int k){
    t[o].lc=t[o].rc=t[o].tg=k;
    t[o].sum=1;
}
void pudw(int o){
    if(t[o].tg) updnode(ls,t[o].tg),updnode(rs,t[o].tg),t[o].tg=0;
}
void build(int o,int l,int r){
    if(l==r){t[o].lc=t[o].rc=wt[l],t[o].sum=1;return;}
    int mid=(l+r)>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pup(o);
}
node query(int o,int l,int r,int x,int y){
    if(x<=l&&r<=y) return t[o];
    pudw(o);
    int mid=l+r>>1;
    if(y<=mid) return query(ls,l,mid,x,y);
    else if(x>mid) return query(rs,mid+1,r,x,y);
    else{
        node ans,L,R;
        L=query(ls,l,mid,x,y),R=query(rs,mid+1,r,x,y);
        ans.lc=L.lc,ans.rc=R.rc,ans.sum=L.sum+R.sum;
        if(L.rc==R.lc) --ans.sum;
        return ans;
    }
    pup(o);
}
void upd(int o,int l,int r,int x,int y,int k){
    if(l==x&&r==y){updnode(o,k);return;}
    int mid=(l+r)>>1;
    pudw(o);
    if(y<=mid)upd(ls,l,mid,x,y,k);
    else if(x>mid)upd(rs,mid+1,r,x,y,k);
    else{
        upd(ls,l,mid,x,mid,k);
        upd(rs,mid+1,r,mid+1,y,k);
    }
    pup(o);
}
void qrange(int x,int y){
    int pre1=-1,pre2=-1,ans=0;node nw;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(pre1,pre2);
        nw=query(1,1,n,dfn[top[x]],dfn[x]);ans+=nw.sum;
        if(nw.rc==pre1) --ans;
        pre1=nw.lc,x=f[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y),swap(pre1,pre2);
    nw=query(1,1,n,dfn[y],dfn[x]);
    ans+=nw.sum;
    if(nw.rc==pre1) --ans;
    if(nw.lc==pre2) --ans;
    printf("%d\n",ans);
}
void Change(int x,int y,int k){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        upd(1,1,n,dfn[top[x]],dfn[x],k);
        x=f[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    upd(1,1,n,dfn[x],dfn[y],k);
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    for(int i=1;i<=n;++i) rd(a[i]);
    for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
    dfs1(1,0),dfs2(1,1),build(1,1,n);
    char ch[5];int x,y,k;
    while(m--){
        scanf("%s",ch);rd(x),rd(y);
        if(ch[0]=='C') rd(k),Change(x,y,k);
        else qrange(x,y);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/lxyyyy/p/11519355.html