• 【BZOJ2243】【SDOI2011】染色(树链剖分,线段树)


    题面

    我们也要换个花样,这回提供洛谷的题面

    题解

    线段树+树链剖分大水题
    维护颜色段的方法很简单呀。。。
    维护当前区间内的颜色段个数,
    以及当前区间左端和右端的颜色,
    合并的时候考虑是否要减一下就行了
    至于跳LCA进行Modify的时候稍微注意一下细节

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define MAX 110000
    #define lson (now<<1)
    #define rson (now<<1|1)
    using namespace std;
    inline int read()
    {
    	register int x=0,t=1;
    	register char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-'){t=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    	return x*t;
    }
    struct Line
    {
    	int v,next;
    }e[MAX<<1];
    int h[MAX],cnt=1;
    struct Node
    {
    	int c;
    	int lc,rc;
    	int ly;
    }t[MAX<<2];
    inline void Add(int u,int v)
    {
    	e[cnt]=(Line){v,h[u]};
    	h[u]=cnt++;
    }
    int n,m,c[MAX],tim;
    int dfn[MAX],dep[MAX],line[MAX],ff[MAX],size[MAX],hson[MAX],top[MAX];
    void dfs1(int u,int fa)
    {
    	size[u]=1;dep[u]=dep[fa]+1;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==fa)continue;
    		ff[v]=u;
    		dfs1(v,u);
    		size[u]+=size[v];
    		if(size[v]>size[hson[u]])hson[u]=v;
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp;dfn[u]=++tim;line[tim]=u;
    	if(hson[u])dfs2(hson[u],tp);
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(v==hson[u]||v==ff[u])continue;
    		dfs2(v,v);
    	}
    }
    void pushup(int now)
    {
    	t[now].c=t[lson].c+t[rson].c;
    	if(t[lson].rc==t[rson].lc)t[now].c--;
    	t[now].lc=t[lson].lc;
    	t[now].rc=t[rson].rc;
    }
    void pushdown(int now)
    {
    	if(t[now].ly)
    	{
    		t[lson].ly=t[rson].ly=t[lson].lc=t[now].ly;
    		t[rson].lc=t[lson].rc=t[rson].rc=t[now].ly;
    		t[lson].c=t[rson].c=1;
    		t[now].ly=0;
    	}
    }
    void putlazy(int now,int ly)
    {
    	t[now].c=1;
    	t[now].lc=t[now].rc=ly;
    	t[now].ly=ly;
    }
    void Build(int now,int l,int r)
    {
    	if(l==r)
    	{
    		t[now].lc=t[now].rc=c[line[l]];
    		t[now].c=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	Build(lson,l,mid);Build(rson,mid+1,r);
    	pushup(now);
    	t[now].lc=t[lson].lc;
    	t[now].rc=t[rson].rc;
    }
    int getl(int now,int l,int r,int al)
    {
    	if(al==l)return t[now].lc;
    	pushdown(now);
    	int mid=(l+r)>>1;
    	int re;
    	if(mid>=al)re=getl(lson,l,mid,al);
    	else re=getl(rson,mid+1,r,al);
    	pushup(now);
    	return re;
    }
    int getr(int now,int l,int r,int ar)
    {
    	if(r==ar)return t[now].rc;
    	pushdown(now);
    	int mid=(l+r)>>1;
    	int re;
    	if(mid>=ar)re=getr(lson,l,mid,ar);
    	else re=getr(rson,mid+1,r,ar);
    	pushup(now);
    	return re;
    }
    int Query(int now,int l,int r,int al,int ar)
    {
    	if(l==al&&r==ar)return t[now].c;
    	pushdown(now);
    	int mid=(l+r)>>1;
    	int re;
    	if(ar<=mid)re=Query(lson,l,mid,al,ar);
    	else if(al>mid)re=Query(rson,mid+1,r,al,ar);
    	else re=(Query(lson,l,mid,al,mid)+Query(rson,mid+1,r,mid+1,ar)-(t[lson].rc==t[rson].lc?1:0));
    	return re;
    }
    void Modify(int now,int l,int r,int al,int ar,int cc)
    {
    	if(l==al&&r==ar)
    	{
    		putlazy(now,cc);return;
    	}
    	int mid=(l+r)>>1;
    	pushdown(now);
    	if(ar<=mid)Modify(lson,l,mid,al,ar,cc);
    	else if(al>mid)Modify(rson,mid+1,r,al,ar,cc);
    	else
    	{
    		Modify(lson,l,mid,al,mid,cc);
    		Modify(rson,mid+1,r,mid+1,ar,cc);
    	}
    	pushup(now);
    }
    int Answer(int u,int v)
    {
    	int ans=0;
    	int lu=-1,lv=-1;
    	while(top[u]!=top[v])
    	{
    		if(dep[top[u]]<dep[top[v]])swap(u,v),swap(lu,lv);
    		int cl=getl(1,1,n,dfn[top[u]]),cr=getr(1,1,n,dfn[u]);
    		ans+=Query(1,1,n,dfn[top[u]],dfn[u]);
    		if(cr==lu)ans--;
    		lu=cl;
    		u=ff[top[u]];
    	}
    	if(dep[u]>dep[v])swap(u,v),swap(lu,lv);
    	ans+=Query(1,1,n,dfn[u],dfn[v]);
    	int cl=getl(1,1,n,dfn[u]),cr=getr(1,1,n,dfn[v]);
    	if(cl==lu)--ans;
    	if(cr==lv)--ans;
    	return ans;
    }
    void Change(int u,int v,int cc)
    {
    	while(top[u]!=top[v])
    	{
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		Modify(1,1,n,dfn[top[u]],dfn[u],cc);
    		u=ff[top[u]];
    	}
    	if(dep[u]>dep[v])swap(u,v);
    	Modify(1,1,n,dfn[u],dfn[v],cc);
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)c[i]=read();
    	for(int i=1;i<n;++i)
    	{
    		int u=read(),v=read();
    		Add(u,v);Add(v,u);
    	}
    	dfs1(1,0);dfs2(1,1);
    	Build(1,1,n);
    	char ch[5];
    	while(m--)
    	{
    		scanf("%s",ch);
    		if(ch[0]=='C')
    		{
    			int a=read(),b=read(),c=read();
    			Change(a,b,c);
    		}
    		else
    		{
    			int a=read(),b=read();
    			printf("%d
    ",Answer(a,b));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    React Children 使用
    Redux 中间件和异步操作
    Redux 核心概念
    React 的setState 异步理解
    JS 中类型和类型转换
    ES6 新增集合----- Set 和Map
    ES6 新增基本数据类型Symbol
    ES6 解构赋值
    ES6 对象增强
    ES6 中的let 和 const
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7673821.html
Copyright © 2020-2023  润新知