zoukankan      html  css  js  c++  java
  • [SDOI2011]染色

    题目描述

    输入输出格式

    输入格式:

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    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
    
    输出样例#1: 复制
    3
    1
    2
    

    说明


    题解

        这道题目不是很难做,但是很难调

        怎么个难调法

        1.跳lca时要注意两条链并入时的颜色是否相同

        2.询问有多少个颜色块的query中,l,r 区间不是平常的线段树,我们也要考虑l,r区间的左右端点颜色是否相同。

        3,要处理的东西贼多


    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=500001;
    int n,m,tot,num,head[N],size[N],son[N],ch[N];
    int color[N*4],top[N],dep[N*4],ll[N*4],rr[N*4],sum[N*4],a[N],l[N],fa[N],lazy[N*4];
    struct node{
        int next,v,to;
    }e[N*2];
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void add(int from,int to)
    {    
        num++;
        e[num].to=to;
    //    e[num].v=v;
        e[num].next=head[from];
        head[from]=num;
    }
    
    void dfs1(int x,int ff)
    {
        size[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!dep[v])
            {
                dep[v]=dep[x]+1;
                fa[v]=x;
                dfs1(v,x);
                size[x]+=size[v];
                if(size[son[x]]<size[v])son[x]=v;
            }
        }
        return;
    }
    
    void dfs2(int x,int fx)
    {
        l[x]=++tot;a[tot]=ch[x];top[x]=fx;
        if(son[x])dfs2(son[x],fx);
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v!=fa[x]&&v!=son[x])
            {
                dfs2(v,v);
            }
        }
        return ;
    }
    
    void pushup(int root,int l,int r)
    {
        if(ll[root<<1|1]!=rr[root<<1])
        {
            sum[root]=sum[root<<1|1]+sum[root<<1];
        }
        else sum[root]=sum[root<<1|1]+sum[root<<1]-1;
        ll[root]=ll[root<<1];rr[root]=rr[root<<1|1];
        return ;
    }
    
    void build(int root,int l,int r)
    {
        if(l==r)
        {
            color[root]=a[l];
            ll[root]=a[l];
            rr[root]=a[l];
            sum[root]=1;
            return ;
        }
        int mid=(l+r)/2;
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        pushup(root,l,r);
        return ;
    }
    
    void push(int root,int l,int r)
    {
        //int mid=(l+r)>>1;
        lazy[root<<1]=lazy[root];
        lazy[root<<1|1]=lazy[root];
        sum[root<<1]=1;
        sum[root<<1|1]=1;
        ll[root<<1]=lazy[root];
        rr[root<<1]=lazy[root];
        rr[root<<1|1]=lazy[root];
        ll[root<<1|1]=lazy[root];
        color[root<<1]=lazy[root];
        color[root<<1|1]=lazy[root];
        lazy[root]=0;
        return ;
    }
    
    void update(int root,int left,int right,int l,int r,int v)
    {
        if(left>r||right<l)return ;
        if(left>=l&&right<=r)
        {
            lazy[root]=v;
            sum[root]=1;
            ll[root]=rr[root]=color[root]=v;
            return ;
        }
        if(lazy[root])push(root,left,right);
        int mid=(left+right)>>1;
        if(mid>=l)update(root<<1,left,mid,l,r,v);
        if(mid<r) update(root<<1|1,mid+1,right,l,r,v);
        pushup(root,left,right);    
        return ;
    }
    
    int query(int root,int left,int right,int l,int r)
    {
        if(left>=l&&right<=r)return sum[root];
        if(left>r||right<l)return 0;
        int mid=(left+right)>>1;
        if(lazy[root])push(root,left,right);
        int a=0,b=0;
        if(r<=mid)a=query(root<<1,left,mid,l,r);
        else if(mid<l) b=query(root<<1|1,mid+1,right,l,r);
        else {
            int res=query(root<<1,left,mid,l,r)+query(root<<1|1,mid+1,right,l,r);
            if(ll[root<<1|1]==rr[root<<1])res--;
            return res;
        }
        return a+b;
    }
    
    void change_cal(int x,int y,int v)
    {
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy]){swap(fx,fy);swap(x,y);}
            update(1,1,n,l[fx],l[x],v);
            x=fa[fx];fx=top[x];
        }
        if(l[x]>l[y])swap(x,y);
        update(1,1,n,l[x],l[y],v);
    }
    
    int query2(int root,int left,int right,int pos)
    {
        if(left>pos||right<pos)return 0;
        if(left==pos&&right==pos)return color[root];
        int mid=(left+right)>>1;
        if(lazy[root])push(root,left,right);
        int a=0,b=0;
        if(pos<=mid)a=query2(root<<1,left,mid,pos);
        if(pos>mid)b=query2(root<<1|1,mid+1,right,pos);
        return a+b;
    }
    
    int find(int x)
    {
        return query2(1,1,n,l[x]);
    }
    
    int query_cal(int x,int y)
    {
        int ans=0;
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy]){swap(fx,fy);swap(x,y);}
            ans+=query(1,1,n,l[fx],l[x]);
            if(find(fa[fx])==find(fx))ans--;
            x=fa[fx];fx=top[x];
        }
        if(l[x]>l[y])swap(x,y);
        ans+=query(1,1,n,l[x],l[y]);
        return ans;
    }
    
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            ch[i]=read();
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        dep[1]=1;fa[1]=0;
        dfs1(1,1);
    //    cout<<"qwq"<<endl;
        dfs2(1,1);
    //    cout<<"QAQ"<<endl;
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            char qwq;cin>>qwq;
            int x=read(),y=read();
            if(qwq=='Q')
            {
                printf("%d
    ",query_cal(x,y));
            }
            else 
            {
                int z=read();
                change_cal(x,y,z);
            }
        }
        return 0;
    }
  • 相关阅读:
    .NET 应用架构指导 V2 [1]
    MSSQL优化之————探索MSSQL执行计划
    删除代码中所有的空行
    微软企业库5.0学习笔记(一)企业库是什么?
    C# MP3操作类
    Microsoft Enterprise Library 5.0系列学习笔记【1】
    基于Asp.net的CMS系统We7架设实验(环境WIN7,SQL2005,.NET3.5)(初学者参考贴) 【转】
    C#中用ILMerge将所有引用的DLL和exe文件打成一个exe文件,有图解
    “Singleton”模式
    阅读技术类图书的思考
  • 原文地址:https://www.cnblogs.com/hhh1109/p/8780553.html
Copyright © 2011-2022 走看看