[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\n",query_cal(x,y));
        }
        else 
        {
            int z=read();
            change_cal(x,y,z);
        }
    }
    return 0;
}

 

posted @ 2018-04-10 17:00  Epiphyllum_thief  阅读(159)  评论(0编辑  收藏  举报