ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2486 [SDOI2011]染色

2022-05-09 16:32:47  阅读:161  来源: 互联网

标签:颜色 leq int 染色 空格 SDOI2011 P2486 节点 define


题目链接

P2486 [SDOI2011]染色

给定一棵 \(n\) 个节点的无根树,共有 \(m\) 个操作,操作分为两种:

  1. 将节点 \(a\) 到节点 \(b\) 的路径上的所有点 (包括 \(a\) 和 \(b\) ) 都染成颜色 \(c\) 。
  2. 询问节点 \(a\) 到节点 \(b\) 的路径上的颜色段数量。

颜色段的定义是极长的连续相同颜色被认为是一段。例如 112221 由三段组成:112221

输入格式

输入的第一行是用空格隔开的两个整数,分别代表树的节点个数 \(n\) 和操作个数 \(m\) 。
第二行有 \(n\) 个用空格隔开的整数,第 \(i\) 个整数 \(w_{i}\) 代表结点 \(i\) 的初始颜色。
第 \(3\) 到第 \((n+1)\) 行,每行两个用空格隔开的整数 \(u, v\) ,代表树上存在一条连结节点 \(u\) 和节点 \(v\) 的边。
第 \((n+2)\) 到第 \((n+m+1)\) 行,每行描述一个操作,其格式为:
每行首先有一个字符 \(o p\) ,代表本次操作的类型。

  • 若 \(o p\) 为 C ,则代表本次操作是一次染色操作,在一个空格后有三个用空格隔开的整数 \(a, b, c\) ,代表将 \(a\) 到 \(b\) 的路径上所有点都染成颜色 \(c_{\text {。 }}\)
  • 若 \(o p\) 为 Q,则代表本次操作是一次查询操作,在一个空格后有两个用空格隔开的整数 \(a, b\) ,表示查询 \(a\) 到 \(b\) 路径上的颜色段数量。

输出格式

对于每次查询操作,输出一行一个整数代表答案。

输入输出样例

输入

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

输出

3
1
2

说明/提示

数据规模与约定

对于 \(100 \%\) 的数据, \(1 \leq n, m \leq 10^{5} , 1 \leq w_{i}, c \leq 10^{9} , 1 \leq a, b, u, v \leq n\) ,\(op\)一定为 \(\mathrm{C}\) 或 \(Q\) , 保证给出的图是一棵树。

解题思路

树链剖分

利用树链剖分思想将问题转换为一段连续区间上的操作,即统计区间上颜色段的数量,对于一段区间来说,先分为左右部分,统计左右部分颜色段的数量之和,如果左部分和右部分中间的颜色一样则说明该颜色段重复计算了,减一即可,所以线段树中应该存储的信息有 区间颜色段区间左边颜色区间右边颜色,但由于自上而下更新时如果当前区间完全在修改区间内,这时会直接返回,下面范围更小的区间还没有更新,所以需要打懒标记。另外树链剖分形成的区间可能是多段,段与段之间也可能出现相同颜色,这时也会重复,查询时记录两边相邻的颜色,最后处理哪一段判断相应的颜色是否相等即可

  • 时间复杂度:\(O((n+m)\times logn)\)

代码

// Problem: P2486 [SDOI2011]染色
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2486
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5;
int n,m,c[N],nc[N],id[N],cnt,sz[N],fa[N],dep[N],son[N],top[N];
vector<int> adj[N];
struct T
{
	int l,r;
	int lc,rc,sum,col;
}tr[N<<2];
void pushup(int u)
{
	tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
	if(tr[u<<1].rc==tr[u<<1|1].lc)tr[u].sum--;
	tr[u].lc=tr[u<<1].lc;
	tr[u].rc=tr[u<<1|1].rc;
}
void pushdown(int u)
{
	if(tr[u].col)
	{
		tr[u<<1].lc=tr[u<<1].rc=tr[u<<1|1].lc=tr[u<<1|1].rc=tr[u].col;
		tr[u<<1].col=tr[u<<1|1].col=tr[u].col;
		tr[u<<1].sum=tr[u<<1|1].sum=1;
		tr[u].col=0;
	}
}
void build(int u,int l,int r)
{
	tr[u]={l,r};
	if(l==r)
	{
		tr[u].lc=tr[u].rc=nc[l];
		tr[u].sum=1;
		return ;
	}
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	pushup(u);
}

void update(int u,int l,int r,int d)
{
	if(l<=tr[u].l&&tr[u].r<=r)
	{
		tr[u].lc=tr[u].rc=tr[u].col=d;
		tr[u].sum=1;
		return ;
	}
	pushdown(u);
	int mid=tr[u].l+tr[u].r>>1;
	if(l<=mid)update(u<<1,l,r,d);
	if(r>mid)update(u<<1|1,l,r,d);
	pushup(u);
}
T ask(int u,int l,int r)
{
	if(l<=tr[u].l&&tr[u].r<=r)return tr[u];
	int mid=tr[u].l+tr[u].r>>1;
	pushdown(u);
	if(l<=mid&&r>mid)
	{
		T res;
		T L=ask(u<<1,l,r),R=ask(u<<1|1,l,r);
		res.sum=L.sum+R.sum;
		res.lc=L.lc,res.rc=R.rc;
		if(L.rc==R.lc)
			res.sum--;
		return res;
	}
	if(l<=mid)return ask(u<<1,l,r);
	return ask(u<<1|1,l,r);
}
void update_path(int x,int y,int d)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,id[top[x]],id[x],d);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	update(1,id[y],id[x],d);
}
int ask_path(int x,int y)
{
	int res=0,lx=0,ly=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y),swap(lx,ly);
		T t=ask(1,id[top[x]],id[x]);
		res+=t.sum;
		if(t.rc==lx)res--;
		lx=t.lc;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y])swap(x,y),swap(lx,ly);
	T t=ask(1,id[x],id[y]);
	res+=t.sum;
	if(t.lc==lx)res--;
	if(t.rc==ly)res--;
	return res;
}
void dfs1(int x,int father,int depth)
{
	fa[x]=father,sz[x]=1,dep[x]=depth;
	for(int y:adj[x])
	{
		if(y==father)continue;
		dfs1(y,x,depth+1);
		sz[x]+=sz[y];
		if(sz[son[x]]<sz[y])son[x]=y;
	}
}
void dfs2(int x,int t)
{
	id[x]=++cnt,nc[cnt]=c[x],top[x]=t;
	if(!son[x])return ;
	dfs2(son[x],t);
	for(int y:adj[x])
	{
		if(y==fa[x]||y==son[x])continue;
		dfs2(y,y);
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&c[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		adj[x].pb(y),adj[y].pb(x);
	}    
	dfs1(1,1,1);
	dfs2(1,1);
	build(1,1,n);
	while(m--)
	{
		char op[2];
		int a,b,c;
		scanf("%s%d%d",op,&a,&b);
		if(*op=='C')
		{
			scanf("%d",&c);
			update_path(a,b,c);
		}
		else
			printf("%d\n",ask_path(a,b));
	}
    return 0;
}

标签:颜色,leq,int,染色,空格,SDOI2011,P2486,节点,define
来源: https://www.cnblogs.com/zyyun/p/16249668.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有