BZOJ 2234 Dyeing (Tree Chaining)

Title:

Ideas:

Tree chain division + line segment tree merging
It is obvious that the tree chain division is divided, but it is a bit difficult to maintain. First of all, we still have to use the nature of the tree chain division. The numbers from the root to the leaf are from small to large, then we know Now, for a pair of points, in the process of climbing one of the points to their LCA, the interval obtained by the line segment tree is continuous, and for two intervals, if the color of the endpoints at the connection of the two intervals is the same, then To reduce ans by one

Mistakes and Reflections:

The idea is actually not difficult, but if there is a bug, it is very uncomfortable. When you look at the question, you know that it takes 200 lines. It is a bit mentally polluted to write. The
left and right endpoints are a bit small. . . think more

Code:

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct edge{
    int to,next;
}e[N*2];
int num[N*4],lk[N*4],rk[N*4],lazy[N*4];//segtree
int tot,tid,q,n;
int top[N],si[N],fa[N],first[N],son[N],depth[N],id[N],val[N],rnk[N];
char ta[10];

void addedge(int x,int y){
    e[tot].to=y;
    e[tot].next=first[x];
    first[x]=tot++;
    e[tot].to=x;
    e[tot].next=first[y];
    first[y]=tot++;
}

void dfs1(int now,int bef,int dep){
    fa[now]=bef;
    depth[now]=dep;
    si[now]=1;
    for(int i=first[now];i!=-1;i=e[i].next)
        if(e[i].to!=bef){
            dfs1(e[i].to,now,dep+1);
            si[now]+=si[e[i].to];
            if(son[now]==-1) son[now]=e[i].to;
            else son[now]=si[e[i].to]>si[son[now]]?e[i].to:son[now];
        }
}

void dfs2(int now,int tp){
    top[now]=tp;
    id[now]=tid++;
    if(son[now]!=-1) dfs2(son[now],tp);
    for(int i=first[now];i!=-1;i=e[i].next)
        if(e[i].to!=fa[now]&&e[i].to!=son[now])
            dfs2(e[i].to,e[i].to);
}

void init(){
    memset(lazy,-1,sizeof(lazy));
    tot=0; tid=1;
    memset(first,-1,sizeof(first));
    memset(son,-1,sizeof(son));
}

void pushup(int rt){
    lk[rt]=lk[rt<<1];
    rk[rt]=rk[rt<<1|1];
    num[rt]=num[rt<<1]+num[rt<<1|1]-(rk[rt<<1]==lk[rt<<1|1]);
}

void pushdown(int rt){
    if(lazy[rt]!=-1){
        num[rt<<1]=1;
        lk[rt<<1]=lazy[rt];
        rk[rt<<1]=lazy[rt];
        lazy[rt<<1]=lazy[rt];

        num[rt<<1|1]=1;
        lk[rt<<1|1]=lazy[rt];
        rk[rt<<1|1]=lazy[rt];
        lazy[rt<<1|1]=lazy[rt];

        lazy[rt]=-1;
    }
}
//初始化
void build(int l,int r,int rt){
    if(l==r){
        num[rt]=1;
        lk[rt]=val[rnk[l]];
        rk[rt]=val[rnk[l]];
        return ;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(rt);
}
//染色
void change(int v,int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r){
        lazy[rt]=v;
        lk[rt]=v;
        rk[rt]=v;
        num[rt]=1;
        return ;
    }
    pushdown(rt);
    int m=(l+r)/2;
    if(m>=L) change(v,L,R,lson);
    if(m<R) change(v,L,R,rson);
    pushup(rt);
    return ;
}
//找出这段的个数和端点颜色
int query(int &lc,int &rc,int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r){
        if(L==l) lc=lk[rt];
        if(R==r) rc=rk[rt];
        return num[rt];
    }
    pushdown(rt);
    int m=(l+r)/2;
    int ans=0;
    bool z=false,y=false;
    if(m>=L){
        ans+=query(lc,rc,L,R,lson);
        z=true;
    }
    if(m<R){
        ans+=query(lc,rc,L,R,rson);
        y=true;
    }
    pushup(rt);
    if(z&&y)
        ans-=rk[rt<<1]==lk[rt<<1|1];
    return ans;
}

//染色
void modify(int L,int R,int v)
{
    int f1=top[L],f2=top[R];
    while(f1!=f2)
    {
        if(depth[f1]<depth[f2])
        {
            swap(f1,f2);
            swap(L,R);
        }
        change(v,id[f1],id[L],1,n,1);
        L=fa[f1];
        f1=top[L];
    }
    if(depth[L]>depth[R]) swap(L,R);
    change(v,id[L],id[R],1,n,1);
}

//找段数
int solve(int L,int R)
{
    int f1=top[L],f2=top[R];
    int ans=0,lo=-1,ro=-1;
    while(f1!=f2)
    {
        if(depth[f1]<depth[f2]){
            int tb,tc;
            ans+=query(tb,tc,id[f2],id[R],1,n,1);
            if(tc==ro) ans--;
            ro=tb;
            R=fa[f2];
            f2=top[R];
        }
        else{
            int tb,tc;
            ans+=query(tb,tc,id[f1],id[L],1,n,1);
            if(tc==lo) ans--;
            lo=tb;
            L=fa[f1];
            f1=top[L];
        }
    }
    if(depth[L]>depth[R]){
        int tb,tc;
        ans+=query(tb,tc,id[R],id[L],1,n,1);
        if(tc==lo) ans--;
        if(tb==ro) ans--;
    }
    else{
        int tb,tc;
        ans+=query(tb,tc,id[L],id[R],1,n,1);
        if(tb==lo) ans--;
        if(tc==ro) ans--;
    }
    return ans;
}

int main(){
    init();
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=0,u,v;i<n-1;i++){
        scanf("%d%d",&u,&v);
        addedge(u,v);
    }
    dfs1(1,1,1);
    dfs2(1,1);
    for(int i=1;i<=n;i++)
        rnk[id[i]]=i;
    build(1,n,1);
    while(q--){
        scanf("%s",ta);
        if(ta[0]=='Q'){
            int tb,tc;
            scanf("%d%d",&tb,&tc);
            printf("%d\n",solve(tb,tc));
        }
        else{
            int tb,tc,td;
            scanf("%d%d%d",&tb,&tc,&td);
            modify(tb,tc,td);
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324642839&siteId=291194637