• bzoj2243


    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 6753  Solved: 2496
    [Submit][Status][Discuss]

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数nm,分别表示节点数和操作数;

    第二行包含n个正整数表示n个节点的初始颜色

    下面行每行包含两个整数xy,表示xy之间有一条无向边。

    下面行每行描述一个操作:

    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括ab)都染成颜色c

    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括ab)路径上的颜色段数量。

    Output

    对于每个询问操作,输出一行答案。

    Sample Input

    6 5

    2 2 1 2 1 1

    1 2

    1 3

    2 4

    2 5

    2 6

    Q 3 5

    C 2 1 1

    Q 3 5

    C 5 1 2

    Q 3 5

    Sample Output

    3

    1

    2

    HINT

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

    Source

    第一轮day1

    树链剖分练习。

    1.每次查询时记得跳上去时,要把两个端点是否相等计算进去。color[num[fa[top[x]]]]==color[num[top[x]]]记得判断,这里用单点查询即可。

    (这里不会出现错误,有人会想:fa[top[x]]会不会跳到了这两个点的路径外?不会,因为当dep[top[x]]<dep[top[x]时交换x,y所以当x已经在最上面的区间时,他就不会动了,只有y会向上跳)

    2.每次查询时query(l,mid) query(mid+1,r)时也要判断rc[x*2]==lc[x*2+1](查询时)当且仅当a<=mid<b时要判断;(a,b是要查询的区间),因为如果这两个端点不在查询的区间里,那么也就没有必要判断了。

    3.tag要先变成-1,颜色可能为0

    4.pushdown是把下面节点的信息修改,不是仅仅修改他的tag。(不清楚)

    一组数据:

    7 3
    1 1 1 1 1 1 1
    1 2 1 3
    2 4 2 5
    3 6 3 7
    C 6 3 2
    C 4 7 1
    Q 6 7

    这组数据说明了第二条

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 200010
    struct edge 
    {
        int to,nxt;
    }e[N];
    int n,m,cnt,k;
    int head[N],size[N],rc[N<<2],lc[N<<2],sum[N<<2],tag[N<<2];
    int num[N],c[N],fa[N],top[N],son[N],dep[N];
    void link(int u,int v)
    {
        e[++cnt].nxt=head[u];
        head[u]=cnt;
        e[cnt].to=v;
    }
    int min(int x,int y)
    {
        return x<y?x:y;
    }
    int max(int x,int y)
    {
        return x>y?x:y;
    }
    void dfs1(int u,int Fa)
    {
        int Max=0; size[u]=1;
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v!=Fa)
            {
                fa[v]=u;
                dep[v]=dep[u]+1;
                dfs1(v,u);
                if(size[v]>Max)
                {
                    son[u]=v;
                    Max=size[v];
                }
                size[u]+=size[v];
            }
        }
    }
    void dfs2(int u,int acs,int Fa)
    {
        top[u]=acs; num[u]=++k;
        if(son[u]) dfs2(son[u],acs,u);
        for(int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v!=Fa&&v!=son[u]) dfs2(v,v,u);
        }
    }
    void pushdown(int x)
    {
        if(tag[x]!=-1)
        {
            tag[x*2+1]=tag[x*2]=tag[x];
            sum[x*2+1]=sum[x*2]=1;
            lc[x*2+1]=lc[x*2]=rc[x*2+1]=rc[x*2]=tag[x];
            tag[x]=-1;
        }
    }
    void update(int l,int r,int x,int a,int b,int c)
    {
        if(l>b||r<a) return;
        if(l>=a&&r<=b)
        {
            tag[x]=lc[x]=rc[x]=c; 
            sum[x]=1;
            return;
        }
        if(r<=b) rc[x]=c;
        if(l>=a) lc[x]=c;
        pushdown(x);
        update(l,(l+r)/2,x*2,a,b,c);
        update((l+r)/2+1,r,x*2+1,a,b,c);
        sum[x]=sum[x*2]+sum[x*2+1]-(rc[x*2]==lc[x*2+1]);
    }
    int query(int l,int r,int x,int a,int b)
    {
        if(l>b||r<a) return 0;
        if(l>=a&&r<=b) return sum[x];
        pushdown(x);
        int ret=0;
        ret+=query(l,(l+r)/2,x*2,a,b);
        ret+=query((l+r)/2+1,r,x*2+1,a,b);
        if((l+r)/2>=a&&(l+r)/2<b) ret-=(rc[x*2]==lc[x*2+1]);
        return ret;
    }
    int pquery(int l,int r,int x,int pos)
    {
        if(l==r) return tag[x];
        pushdown(x);
        if(pos>(l+r)/2) return pquery((l+r)/2+1,r,x*2+1,pos);
        else return pquery(l,(l+r)/2,x*2,pos);
    }
    void ask(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans+=query(1,n,1,num[top[x]],num[x]);
    //        printf("color=%d
    ",pquery(1,n,1,num[fa[top[x]]]));
            ans-=(pquery(1,n,1,num[top[x]])==pquery(1,n,1,num[fa[top[x]]]));        
            x=fa[top[x]];
        }
        ans+=query(1,n,1,min(num[x],num[y]),max(num[x],num[y]));
        printf("%d
    ",ans);
    }
    void change(int x,int y,int c)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            update(1,n,1,num[top[x]],num[x],c);
            x=fa[top[x]];
        }
        update(1,n,1,min(num[x],num[y]),max(num[x],num[y]),c);
    }
    int main()
    {
        memset(tag,-1,sizeof(tag));
    //    lc[0]=rc[0]=-1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
        }
        for(int i=1;i<n;i++)
        {
            int u,v; scanf("%d%d",&u,&v);
            link(u,v); link(v,u);
        }
        dfs1(1,0);
        dfs2(1,1,0);
        for(int i=1;i<=n;i++)
        {
            update(1,n,1,num[i],num[i],c[i]);
        }
        while(m--)
        {
            char s[10]; scanf("%s",s);    
            if(s[0]=='Q')
            {
                int x,y; scanf("%d%d",&x,&y);
                ask(x,y);
            }
            if(s[0]=='C')
            {
                int x,y,c; scanf("%d%d%d",&x,&y,&c);
                change(x,y,c);
            }    
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    极大似然估计理解与应用
    逻辑回归理解及代码实现
    《剑指offer》---数值的整数次方
    线性回归理解及代码实现
    二叉搜索树(BST)---python实现
    《剑指offer》---顺时针打印矩阵
    《剑指offer》---二进制中1的个数
    《剑指offer》---输出链表倒数第k个结点
    版本控制-Git服务器搭建和常用命令使用
    hbase伪分布式平台搭建(centos 6.3)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6250350.html
Copyright © 2020-2023  润新知