• 2243: [SDOI2011]染色 树链剖分+线段树染色


    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。
    请你写一个程序依次完成这m个操作=。
    题解:树链剖分+线段树,线段树维护区间左右的颜色和种类数,合并就很简单了,考虑左区间的右端点和右区间的左端点是不是一样颜色,然后树上暴跳的时候要比较深度来跳了,然后修改也是在树上暴跳即可
    /**************************************************************
        Problem: 2243
        User: walfy
        Language: C++
        Result: Accepted
        Time:5192 ms
        Memory:48268 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
     
    using namespace std;
     
    const double g=10.0,eps=1e-12;
    const int N=400000+10,maxn=400000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    struct edge{
        int to,Next;
    }e[maxn];
    int cnt,head[N];
    int son[N],fa[N],top[N],sz[N],id[N];
    int res,w[N],re[N],dep[N];
    void add(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].Next=head[u];
        head[u]=cnt++;
    }
    void init()
    {
        cnt=0;
        memset(head,-1,sizeof head);
        memset(son,-1,sizeof son);
    }
    void dfs1(int u,int f,int de)
    {
        fa[u]=f;sz[u]=1;
        dep[u]=de;
        for(int i=head[u];~i;i=e[i].Next)
        {
            int v=e[i].to;
            if(v!=f)
            {
                dfs1(v,u,de+1);
                sz[u]+=sz[v];
                if(son[u]==-1||sz[v]>sz[son[u]])son[u]=v;
            }
        }
    }
    void dfs2(int u,int f,int tp)
    {
        top[u]=tp;
        id[u]=++res;
        if(son[u]!=-1)dfs2(son[u],u,tp);
        for(int i=head[u];~i;i=e[i].Next)
        {
            int v=e[i].to;
            if(v!=f&&v!=son[u])dfs2(v,u,v);
        }
    }
    struct node{
        int cl,cr,co;
    }sum[N<<2];
    node gao(node a,node b)
    {
        if(a.cl==-1)a=b;
        else if(b.cl==-1);
        else
        {
            a.co+=b.co;
            if(a.cr==b.cl)a.co--;
            a.cr=b.cr;
        }
        return a;
    }
    int lazy[N<<2];
    void pushdown(int rt)
    {
        if(lazy[rt]!=-1)
        {
            sum[rt<<1].co=sum[rt<<1|1].co=1;
            sum[rt<<1].cl=sum[rt<<1|1].cl=lazy[rt];
            sum[rt<<1].cr=sum[rt<<1|1].cr=lazy[rt];
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            lazy[rt]=-1;
        }
    }
    void pushup(int rt)
    {
        sum[rt]=gao(sum[rt<<1],sum[rt<<1|1]);
    }
    void build(int l,int r,int rt)
    {
        lazy[rt]=-1;
        if(l==r){sum[rt].cl=sum[rt].cr=w[re[l]];sum[rt].co=1;return ;}
        int m=(l+r)>>1;
        build(ls);build(rs);
        pushup(rt);
    }
    void update(int L,int R,int c,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            sum[rt].co=1,sum[rt].cl=sum[rt].cr=c;
            lazy[rt]=c;
            return ;
        }
        pushdown(rt);
        int m=(l+r)>>1;
        if(L<=m)update(L,R,c,ls);
        if(m<R)update(L,R,c,rs);
        pushup(rt);
    }
    node query1(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R)return sum[rt];
        pushdown(rt);
        int m=(l+r)>>1;
        node ans{-1,-1,0};
        if(L<=m)ans=gao(ans,query1(L,R,ls));
        if(m<R)ans=gao(ans,query1(L,R,rs));
        return ans;
    }
    int query(int a,int b)
    {
        int f1=top[a],f2=top[b],ans=0;
        node aa{-1,-1,0},bb{-1,-1,0};
        while(f1!=f2)
        {
            if(dep[f1]>dep[f2])
            {
                node te=query1(id[f1],id[a],1,res,1);
                swap(te.cl,te.cr);
                aa=gao(aa,te);
                a=fa[f1];f1=top[a];
            }
            else
            {
                node te=query1(id[f2],id[b],1,res,1);
                swap(te.cl,te.cr);
                bb=gao(bb,te);
                b=fa[f2];f2=top[b];
            }
        }
        if(dep[a]<dep[b])
        {
            node te=query1(id[a],id[b],1,res,1);
            aa=gao(aa,te);
            swap(bb.cl,bb.cr);
            aa=gao(aa,bb);
        }
        else
        {
            node te=query1(id[b],id[a],1,res,1);
            swap(te.cl,te.cr);
            aa=gao(aa,te);
            swap(bb.cl,bb.cr);
            aa=gao(aa,bb);
        }
        return aa.co;
    }
    void change(int a,int b,int c)
    {
        int f1=top[a],f2=top[b];
        while(f1!=f2)
        {
            if(dep[f1]<dep[f2])swap(f1,f2),swap(a,b);
            update(id[f1],id[a],c,1,res,1);
            a=fa[f1],f1=top[a];
        }
        if(dep[a]>dep[b])swap(a,b);
    //    printf("%d %d %d %d
    ",id[a],id[b],a,b);
        update(id[a],id[b],c,1,res,1);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        init();
        for(int i=1;i<n;i++)
        {
            int a,b;scanf("%d%d",&a,&b);
            add(a,b);add(b,a);
        }
        dfs1(1,-1,1);
        dfs2(1,-1,1);
        for(int i=1;i<=res;i++)re[id[i]]=i;
        build(1,res,1);
        while(m--)
        {
            char op[10];
            scanf("%s",op);
            if(op[0]=='C')
            {
                int a,b,c;scanf("%d%d%d",&a,&b,&c);
                change(a,b,c);
            }
            else
            {
                int a,b;scanf("%d%d",&a,&b);
                printf("%d
    ",query(a,b));
            }
        }
        return 0;
    }
    /***********************
    8 100
    3 2 2 2  4 1 1 3
    1 3
    1 5
    1 7
    3 6
    3 4
    5 2
    2 8
    ***********************/
    View Code
  • 相关阅读:
    1075: 聚餐人数统计
    1074: 百钱买百鸡
    1072: 青蛙爬井
    1073: 级数求和
    1071: 分解质因子
    1070: 小汽车的位置
    1068: 二进制数
    2019 牛客多校 第六场
    2019 牛客多校 第五场
    2019 牛客多校 第二场
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9022236.html
Copyright © 2020-2023  润新知