题意:给定一棵树,每个节点有一个颜色(105 内个点)。有很多询问操作(105 内个操作),分别为将两点之间的路径上的点的颜色全部设为 c,以及询问两点之间的路径上有多少子段(子段是一段连续的同色点)。

我都不知道我写了写什么。总之两棵枣树在我昏昏沉沉的脑子里挥之不去。

以下就是代码,如果你不喜欢压行。我也没办法。今天下午我无聊至极于是开始压行。

#include <iostream>
#include <cstdio>
#include <cstring>
#define MX 400008
#define ls (node<<1)
#define rs ((node<<1)|1)
#define mid ((l+r)>>1)
using namespace std;
typedef struct tnode{int l,r,sm,lc,rc,p,n;}trnode;
trnode tree[MX];
int fst[MX],nxt[MX],v[MX],col[MX],lnum,n,m,num;
int siz[MX],top[MX],son[MX],dep[MX],fa[MX],rak[MX],ind[MX];
void addeg(int nu,int nv){nxt[++lnum]=fst[nu],fst[nu]=lnum,v[lnum]=nv;}
void input(){
    int a,b,c;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&col[i]);
    for(int i=1;i<n;i++)scanf("%d%d",&a,&b),addeg(a,b),addeg(b,a);
}
void psd(int node){
    int c=tree[node].n;
    if(tree[node].p==0||tree[node].l==tree[node].r)return;
    tree[ls].p=tree[rs].p=1;
    tree[ls].n=tree[rs].n=c;
    tree[ls].sm=tree[rs].sm=1;
    tree[ls].lc=tree[rs].lc=tree[ls].rc=tree[rs].rc=c;
    tree[node].p=0;
}
void upd(int node){
    tree[node].sm=tree[ls].sm+tree[rs].sm-(tree[ls].rc==tree[rs].lc);
    tree[node].lc=tree[ls].lc,tree[node].rc=tree[rs].rc;
}
void build(int node,int l,int r){
    tree[node].l=l,tree[node].r=r,tree[node].p=tree[node].n=0;
    if(l==r)tree[node].sm=1,tree[node].lc=col[rak[l]],tree[node].rc=col[rak[r]];
    else build(ls,l,mid),build(rs,mid+1,r),upd(node);
}
void add(int node,int ql,int qr,int x){
    psd(node);
    int l=tree[node].l,r=tree[node].r;
    if(ql<=l&&r<=qr)tree[node].sm=1,tree[node].lc=tree[node].rc=x,tree[node].p=1,tree[node].n=x;
    else if(r<ql||l>qr)return;
    else add(ls,ql,qr,x),add(rs,ql,qr,x),upd(node);
}
int qsm(int node,int ql,int qr){
    psd(node);
    int l=tree[node].l,r=tree[node].r;
    if(ql<=l&&r<=qr)return tree[node].sm;
    if(mid>=qr)return qsm(ls,ql,qr);
    else if(mid<ql)return qsm(rs,ql,qr);
    else return qsm(ls,ql,qr)+qsm(rs,ql,qr)-(tree[ls].rc==tree[rs].lc);
}
int qcl(int node,int p){
    psd(node);
    int l=tree[node].l,r=tree[node].r;
    if(l==r)return tree[node].lc;
    else if(p<=mid)return qcl(ls,p);
    else return qcl(rs,p);
}
void dfs1(int x,int fat,int dp){
    fa[x]=fat,dep[x]=dp,siz[x]=1;
    for(int i=fst[x];i!=-1;i=nxt[i]){
        if(v[i]==fat)continue;
        dfs1(v[i],x,dp+1),siz[x]+=siz[v[i]];
        if(son[x]==-1||siz[v[i]]>siz[son[x]])son[x]=v[i];
    }
}
void dfs2(int x,int tp){
    top[x]=tp,ind[x]=++num,rak[num]=x;
    if(son[x]==-1)return;
    dfs2(son[x],tp);
    for(int i=fst[x];i!=-1;i=nxt[i])if(v[i]!=fa[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
}
void change(int s,int t,int x){
    int fs=top[s],ft=top[t];
    while(fs!=ft){
        if(dep[fs]<dep[ft])swap(s,t),swap(fs,ft);
        add(1,ind[fs],ind[s],x),s=fa[fs],fs=top[s];
    }
    if(dep[s]>dep[t])swap(s,t);
    add(1,ind[s],ind[t],x);
}
int query(int s,int t){
    int fs=top[s],ft=top[t],tot=0,sc=-1,tc=-1;
    while(fs!=ft){
        if(dep[fs]<dep[ft])swap(s,t),swap(fs,ft),swap(sc,tc);
        tot+=qsm(1,ind[fs],ind[s])-(sc==qcl(1,ind[s]));
        sc=qcl(1,ind[fs]),s=fa[fs],fs=top[s];
    }
    if(dep[s]>dep[t])swap(s,t),swap(sc,tc);
    tot+=qsm(1,ind[s],ind[t])-((sc==qcl(1,ind[s]))+(tc==qcl(1,ind[t])));
    return tot;
}
int main(){
    int a,b,c;
    char ch;
    lnum=-1,num=0;
    memset(fst,0xff,sizeof(fst)),memset(son,0xff,sizeof(son));
    input(),dfs1(1,1,1),dfs2(1,1),build(1,1,n);
    for(int i=1;i<=m;i++){
        ch=getchar();
        while(ch!='Q'&&ch!='C')ch=getchar();
        if(ch=='Q')scanf("%d%d",&a,&b),printf("%d\n",query(a,b));
        else scanf("%d%d%d",&a,&b,&c),change(a,b,c);
    }
    return 0;
}
分类: 文章

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注