zoukankan      html  css  js  c++  java
  • bzoj 2243

    2243: [SDOI2011]染色

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 8800  Solved: 3305
    [Submit][Status][Discuss]

    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。
    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数n和m,分别表示节点数和操作数;
    第二行包含n个正整数表示n个节点的初始颜色
    下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
    下面 行每行描述一个操作:
    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

    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

    代码:

    //线段树区间染色查询区间颜色段数量,树剖之后还要考虑两段衔接之后颜色段是否减少。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXN=100009;
    int n,m,fa[MAXN],son[MAXN],lev[MAXN],top[MAXN],id[MAXN],head[MAXN],size[MAXN],val[MAXN];
    int tot,cnt,col[MAXN<<2],tag[MAXN<<2],lef[MAXN<<2],rig[MAXN<<2],a[MAXN],nowr,nowl;
    struct Edge { int to,next; }edge[MAXN<<1];
    void init()
    {
        tot=cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++) fa[i]=top[i]=i;
    }
    void addedge(int x,int y)
    {
        edge[tot].to=y;edge[tot].next=head[x];
        head[x]=tot++;
        edge[tot].to=x;edge[tot].next=head[y];
        head[y]=tot++;
    }
    void dfs1(int x,int d)
    {
        size[x]=1;
        lev[x]=d;
        son[x]=0;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int y=edge[i].to;
            if(y==fa[x]) continue;
            fa[y]=x;
            dfs1(y,d+1);
            size[x]+=size[y];
            if(size[son[x]]<size[y]) son[x]=y;
        }
    }
    void dfs2(int x,int tp)
    {
        id[x]=++cnt;
        top[x]=tp;
        if(son[x]) dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=edge[i].next){
            int y=edge[i].to;
            if(y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    void pushup(int rt)
    {
        lef[rt]=lef[rt<<1];
        rig[rt]=rig[rt<<1|1];
        col[rt]=col[rt<<1]+col[rt<<1|1];
        if(rig[rt<<1]==lef[rt<<1|1]) col[rt]--;
    }
    void build(int rt,int l,int r)
    {
        tag[rt]=-1;
        if(l==r){
            col[rt]=1;
            lef[rt]=rig[rt]=val[l];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    void pushdown(int rt)
    {
        if(tag[rt]!=-1){
            tag[rt<<1]=tag[rt<<1|1]=tag[rt];
            lef[rt<<1]=lef[rt<<1|1]=rig[rt<<1]=rig[rt<<1|1]=tag[rt];
            col[rt<<1]=col[rt<<1|1]=1;
            tag[rt]=-1;
        }
    }
    void update(int ql,int qr,int c,int rt,int l,int r)
    {
        if(ql<=l&&qr>=r){
            tag[rt]=lef[rt]=rig[rt]=c;
            col[rt]=1;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid) update(ql,qr,c,rt<<1,l,mid);
        if(qr>mid) update(ql,qr,c,rt<<1|1,mid+1,r);
        pushup(rt);
    }
    void Update(int ql,int qr,int c)
    {
        int ltp=top[ql],rtp=top[qr];
        while(ltp!=rtp){
            if(lev[rtp]<lev[ltp]){
                swap(ql,qr);
                swap(ltp,rtp);
            }
            update(id[rtp],id[qr],c,1,1,cnt);
            qr=fa[rtp];
            rtp=top[qr];
        }
        if(lev[qr]<lev[ql]) swap(qr,ql);
        update(id[ql],id[qr],c,1,1,cnt);
    }
    int query(int ql,int qr,int rt,int l,int r)
    {
        if(ql==l) nowl=lef[rt];
        if(qr==r) nowr=rig[rt];
        if(ql<=l&&qr>=r) return col[rt];
        pushdown(rt);
        int mid=(l+r)>>1,s=0,lc=-1,rc=-1;
        if(ql<=mid){
            s+=query(ql,qr,rt<<1,l,mid);
            lc=rig[rt<<1];
        }
        if(qr>mid){
            s+=query(ql,qr,rt<<1|1,mid+1,r);
            rc=lef[rt<<1|1];
        }
        if(lc==rc&&lc!=-1) s--;
        return s;
    }
    int Query(int ql,int qr)
    {
        int s=0,ltp=top[ql],rtp=top[qr],lastl=-1,lastr=-1;
        nowl=-1,nowr=-1;
        while(ltp!=rtp){
            if(lev[rtp]<lev[ltp]){
                swap(ql,qr);
                swap(ltp,rtp);
                swap(lastl,lastr);
            }
            s+=query(id[rtp],id[qr],1,1,cnt);
            if(nowr==lastr&&lastr!=-1) s--;
            lastr=nowl;
            qr=fa[rtp];
            rtp=top[qr];
        }
        if(lev[qr]<lev[ql]) { swap(ql,qr);swap(lastl,lastr); }
        s+=query(id[ql],id[qr],1,1,cnt);
        if(nowl==lastl&&lastl!=-1) s--;
        if(nowr==lastr&&lastr!=-1) s--;
        return s;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        dfs1(1,1);
        dfs2(1,1);
        for(int i=1;i<=n;i++) val[id[i]]=a[i];
        build(1,1,cnt);
        while(m--){
            char ch[3];
            int x,y,z;
            scanf("%s",ch);
            if(ch[0]=='Q'){
                scanf("%d%d",&x,&y);
                printf("%d
    ",Query(x,y));
            }else{
                scanf("%d%d%d",&x,&y,&z);
                Update(x,y,z);
            }
        }
        return 0;
    }
  • 相关阅读:
    BGP综合部署
    网络综合部署
    部署LNMP架构
    编译安装Nginx网站服务及优化
    Apache网页优化
    在windows上安装jupyter,配置单机版pyspark
    剑指offer54-字符流中第一个不重复的字符
    在centos001上安装jupyter,配置单机版pyspark
    剑指offer53-表示数值的字符串
    剑指offer50-数组中重复的数字
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7944280.html
Copyright © 2011-2022 走看看