bzoj2243:[SDOI2011]染色

Posted lcxer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2243:[SDOI2011]染色相关的知识,希望对你有一定的参考价值。

传送门

和学长刚,说自己能不写返回值为struct的query并且不写单点查询而AC此题,挣扎了半个小时还是改回去了
直接树链剖分,对于每个节点记一下最左边的和最右边的颜色以及区间内的颜色段数,区间合并一下就好了
对于查询的时候,也合并一下,跳链的时候注意看一下两条链相邻的颜色,判断一下
这个题就没了
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
const int maxn=1e5+10;char p[10];
#define rg register
int n,m,cnt,tmp,pre[maxn*2],nxt[maxn*2],h[maxn],a[maxn],dep[maxn],size[maxn],f[maxn],top[maxn],id[maxn],nid[maxn],sum;
struct oo{int l,r,ls,rs,sum,cov;}s[maxn*4];
void add(int x,int y)
{
    pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
    pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void dfs(int x)
{
    size[x]=1;
    for(rg int i=h[x];i;i=nxt[i])
        if(pre[i]!=f[x])f[pre[i]]=x,dep[pre[i]]=dep[x]+1,dfs(pre[i]),size[x]+=size[pre[i]];
}
void dfs1(int x,int f)
{
    top[x]=f,id[x]=++tmp,nid[tmp]=x;int k=0;
    for(rg int i=h[x];i;i=nxt[i])
        if(dep[pre[i]]>dep[x]&&size[pre[i]]>size[k])k=pre[i];
    if(!k)return ;dfs1(k,f);
    for(rg int i=h[x];i;i=nxt[i])
        if(dep[pre[i]]>dep[x]&&pre[i]!=k)dfs1(pre[i],pre[i]);
}
void update(int x)
{
    s[x].sum=s[x<<1].sum+s[x<<1|1].sum-(s[x<<1].rs==s[x<<1|1].ls);
    s[x].ls=s[x<<1].ls;s[x].rs=s[x<<1|1].rs;
}
void build(int x,int l,int r)
{
    s[x].l=l,s[x].r=r,s[x].cov=-1;int mid=(l+r)>>1;
    if(l==r){s[x].sum=1,s[x].ls=s[x].rs=a[nid[l]];return ;}
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    update(x);
}
void pushdown(int x)
{
    s[x<<1].cov=s[x<<1|1].cov=s[x<<1].ls=s[x<<1].rs=s[x<<1|1].ls=s[x<<1|1].rs=s[x].cov;
    s[x<<1].sum=s[x<<1|1].sum=1;s[x].cov=-1;
}
oo get(int x,int l,int r)
{
    if(l<=s[x].l&&r>=s[x].r)return s[x];
    if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
    if(r<=mid)return get(x<<1,l,r);
    else if(l>mid)return get(x<<1|1,l,r);
    else 
    {
        oo a=get(x<<1,l,r),b=get(x<<1|1,l,r),c;
        c.sum=a.sum+b.sum-(a.rs==b.ls);c.ls=a.ls,c.rs=b.rs;
        return c;
    }
}
oo get(int x,int l)
{
    if(s[x].l==s[x].r)return s[x];
    if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
    if(l<=mid)return get(x<<1,l);else return get(x<<1|1,l);
}
void change(int x,int l,int r,int z)
{
    if(l<=s[x].l&&r>=s[x].r){s[x].cov=z,s[x].sum=1,s[x].ls=s[x].rs=z;return ;}
    if(s[x].cov!=-1)pushdown(x);int mid=(s[x].l+s[x].r)>>1;
    if(l<=mid)change(x<<1,l,r,z);
    if(r>mid)change(x<<1|1,l,r,z);
    update(x);
}
int qsum(int x,int y)
{
    sum=0;oo a,b;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        a=get(1,id[top[x]],id[x]);sum+=a.sum;
        b=get(1,id[f[top[x]]]);sum-=(a.ls==b.rs);
        x=f[top[x]];
    }
    if(id[x]>id[y])swap(x,y);
    a=get(1,id[x],id[y]),sum+=a.sum;
    return sum;
}
void modify(int x,int y,int z)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        change(1,id[top[x]],id[x],z);x=f[top[x]];
    }
    if(id[x]>id[y])swap(x,y);change(1,id[x],id[y],z);
}
int main()
{
    read(n),read(m);
    for(rg int i=1;i<=n;i++)read(a[i]);
    for(rg int i=1,x,y;i<n;i++)read(x),read(y),add(x,y);
    dfs(1),dfs1(1,1),build(1,1,n);
    for(rg int i=1,x,y,z;i<=m;i++)
    {
        scanf("%s",p+1);
        if(p[1]=='Q')read(x),read(y),printf("%d
",qsum(x,y));
        else read(x),read(y),read(z),modify(x,y,z);
    }
}

以上是关于bzoj2243:[SDOI2011]染色的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ2243][SDOI2011]染色

BZOJ2243: [SDOI2011]染色

BZOJ2243: [SDOI2011]染色

bzoj 2243: [SDOI2011]染色

BZOJ2243: [SDOI2011]染色

BZOJ 2243 SDOI 2011染色